From eccde31f79088542dc8aa35bf438e0a00a6f89c2 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 26 Mar 2019 17:54:49 +0100 Subject: [PATCH 001/250] Create .travis.yml --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000000..f04c419589f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +deploy: + provider: pages + skip_cleanup: true + github_token: $GITHUB_TOKEN # Set in the settings page of your repository, as a secure variable + keep_history: true + on: + branch: master From 7645e7a2f2021b91a862f3e970f8e385402b2e31 Mon Sep 17 00:00:00 2001 From: tevans Date: Tue, 26 Mar 2019 18:20:05 +0100 Subject: [PATCH 002/250] Add .ci/build_docs.sh, updated .travis.yml --- .ci/build_docs.sh | 106 ++++++++++++++++++++++++++++++++++++++++++++++ .travis.yml | 39 ++++++++++++++--- 2 files changed, 138 insertions(+), 7 deletions(-) create mode 100644 .ci/build_docs.sh diff --git a/.ci/build_docs.sh b/.ci/build_docs.sh new file mode 100644 index 00000000000..b8fab375429 --- /dev/null +++ b/.ci/build_docs.sh @@ -0,0 +1,106 @@ +#!/bin/sh +################################################################################ +# Title : generateDocumentationAndDeploy.sh +# Date created : 2016/02/22 +# Notes : +__AUTHOR__="Jeroen de Bruijn" +# Preconditions: +# - Packages doxygen doxygen-doc doxygen-latex doxygen-gui graphviz +# must be installed. +# - Doxygen configuration file must have the destination directory empty and +# source code directory with a $(TRAVIS_BUILD_DIR) prefix. +# - An gh-pages branch should already exist. See below for mor info on hoe to +# create a gh-pages branch. +# +# Required global variables: +# - TRAVIS_BUILD_NUMBER : The number of the current build. +# - TRAVIS_COMMIT : The commit that the current build is testing. +# - DOXYFILE : The Doxygen configuration file. +# - TRAVIS_REPO_SLUG : The username / reponame for the repository. +# - GH_REPO_TOKEN : Secure token to the github repository. +# +# For information on how to encrypt variables for Travis CI please go to +# https://docs.travis-ci.com/user/environment-variables/#Encrypted-Variables +# or https://gist.github.com/vidavidorra/7ed6166a46c537d3cbd2 +# For information on how to create a clean gh-pages branch from the master +# branch, please go to https://gist.github.com/vidavidorra/846a2fc7dd51f4fe56a0 +# +# This script will generate Doxygen documentation and push the documentation to +# the gh-pages branch of a repository specified by GH_REPO_REF. +# Before this script is used there should already be a gh-pages branch in the +# repository. +# +################################################################################ + +################################################################################ +##### Setup this script and get the current gh-pages branch. ##### +echo 'Setting up the script...' +# Exit with nonzero exit code if anything fails +set -e + +GH_REPO_ORG=`echo $TRAVIS_REPO_SLUG | cut -d "/" -f 1` +GH_REPO_NAME=`echo $TRAVIS_REPO_SLUG | cut -d "/" -f 2` +GH_REPO_REF="github.com/$GH_REPO_ORG/$GH_REPO_NAME.git" + +# Create a clean working directory for this script. +# Get the current gh-pages branch +cd docs +git clone -b gh-pages https://git@$GH_REPO_REF html +cd html + +##### Configure git. +# Set the push default to simple i.e. push only the current branch. +git config --global push.default simple +# Pretend to be an user called Travis CI. +git config user.name "Travis CI" +git config user.email "travis@travis-ci.org" + +# Remove everything currently in the gh-pages branch. +# GitHub is smart enough to know which files have changed and which files have +# stayed the same and will only update the changed files. So the gh-pages branch +# can be safely cleaned, and it is sure that everything pushed later is the new +# documentation. +rm -rf * + +# Need to create a .nojekyll file to allow filenames starting with an underscore +# to be seen on the gh-pages site. Therefore creating an empty .nojekyll file. +# Presumably this is only needed when the SHORT_NAMES option in Doxygen is set +# to NO, which it is by default. So creating the file just in case. +echo "" > .nojekyll + +################################################################################ +##### Generate the Doxygen code documentation and log the output. ##### +echo 'Generating Doxygen code documentation...' +# Redirect both stderr and stdout to the log file AND the console. +cd .. +doxygen $DOXYFILE 2>&1 | tee doxygen.log + +################################################################################ +##### Upload the documentation to the gh-pages branch of the repository. ##### +# Only upload if Doxygen successfully created the documentation. +# Check this by verifying that the html directory and the file html/index.html +# both exist. This is a good indication that Doxygen did it's work. +if [ -d "html" ] && [ -f "html/index.html" ]; then + + cd html + echo 'Uploading documentation to the gh-pages branch...' + # Add everything in this directory (the Doxygen code documentation) to the + # gh-pages branch. + # GitHub is smart enough to know which files have changed and which files have + # stayed the same and will only update the changed files. + git add --all + + # Commit the added files with a title and description containing the Travis CI + # build number and the GitHub commit reference that issued this build. + git commit -m "Deploy code docs to GitHub Pages Travis build: ${TRAVIS_BUILD_NUMBER}" -m "Commit: ${TRAVIS_COMMIT}" + + # Force push to the remote gh-pages branch. + # The ouput is redirected to /dev/null to hide any sensitive credential data + # that might otherwise be exposed. + git push --force "https://${GH_REPO_TOKEN}@${GH_REPO_REF}" > /dev/null 2>&1 +else + echo '' >&2 + echo 'Warning: No documentation (html) files have been found!' >&2 + echo 'Warning: Not going to push the documentation to GitHub!' >&2 + exit 1 +fi diff --git a/.travis.yml b/.travis.yml index f04c419589f..c29308b00f5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,32 @@ -deploy: - provider: pages - skip_cleanup: true - github_token: $GITHUB_TOKEN # Set in the settings page of your repository, as a secure variable - keep_history: true - on: - branch: master +# This will run on Travis' 'new' container-based infrastructure +sudo: false + +# Blacklist +branches: + except: + - gh-pages + +# Environment variables +env: + global: + - GH_REPO_NAME: AmpGen + - DOXYFILE: $TRAVIS_BUILD_DIR/doc/doxyfile + - GH_REPO_REF: github.com/GooFit/AmpGen.git + +# Install dependencies +addons: + apt: + packages: + - doxygen + - doxygen-doc + - doxygen-latex + - doxygen-gui + - graphviz + +# Build your code e.g. by calling make +script: + - make + +# Generate and deploy documentation +after_success: + - .ci/build_docs.sh From 4e0884a8be82f955f637bef4584e8c78c596c6f3 Mon Sep 17 00:00:00 2001 From: tevans Date: Tue, 26 Mar 2019 18:23:22 +0100 Subject: [PATCH 003/250] Remove make from .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c29308b00f5..a1ced267b09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,13 +19,13 @@ addons: packages: - doxygen - doxygen-doc - - doxygen-latex +# - doxygen-latex - doxygen-gui - graphviz # Build your code e.g. by calling make script: - - make + - echo true # Generate and deploy documentation after_success: From 1de522364b74978dcdd9780286095d45e5d382b5 Mon Sep 17 00:00:00 2001 From: tevans Date: Tue, 26 Mar 2019 18:26:17 +0100 Subject: [PATCH 004/250] Fixes to .travis.yml --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a1ced267b09..bc71785599c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,4 +29,5 @@ script: # Generate and deploy documentation after_success: - - .ci/build_docs.sh + - chmod +x .ci/build_docs.sh + - source .ci/build_docs.sh From 36ee48210ad0637e7339ba26e48067b9f58217a5 Mon Sep 17 00:00:00 2001 From: tevans Date: Tue, 26 Mar 2019 18:31:08 +0100 Subject: [PATCH 005/250] Fix .ci/build_docs.sh --- .ci/build_docs.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/build_docs.sh b/.ci/build_docs.sh index b8fab375429..a2527d3c76d 100644 --- a/.ci/build_docs.sh +++ b/.ci/build_docs.sh @@ -44,6 +44,7 @@ GH_REPO_REF="github.com/$GH_REPO_ORG/$GH_REPO_NAME.git" # Create a clean working directory for this script. # Get the current gh-pages branch +mkdir docs cd docs git clone -b gh-pages https://git@$GH_REPO_REF html cd html From 2e6ac6874313aa4bb3ad79a5417ae2bcc6a42b08 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 26 Mar 2019 18:48:25 +0100 Subject: [PATCH 006/250] fix build_docs.sh --- .ci/build_docs.sh | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/.ci/build_docs.sh b/.ci/build_docs.sh index a2527d3c76d..6fff86cd0f4 100644 --- a/.ci/build_docs.sh +++ b/.ci/build_docs.sh @@ -16,7 +16,8 @@ __AUTHOR__="Jeroen de Bruijn" # - TRAVIS_BUILD_NUMBER : The number of the current build. # - TRAVIS_COMMIT : The commit that the current build is testing. # - DOXYFILE : The Doxygen configuration file. -# - TRAVIS_REPO_SLUG : The username / reponame for the repository. +# - GH_REPO_NAME : The name of the repository. +# - GH_REPO_REF : The GitHub reference to the repository. # - GH_REPO_TOKEN : Secure token to the github repository. # # For information on how to encrypt variables for Travis CI please go to @@ -38,16 +39,13 @@ echo 'Setting up the script...' # Exit with nonzero exit code if anything fails set -e -GH_REPO_ORG=`echo $TRAVIS_REPO_SLUG | cut -d "/" -f 1` -GH_REPO_NAME=`echo $TRAVIS_REPO_SLUG | cut -d "/" -f 2` -GH_REPO_REF="github.com/$GH_REPO_ORG/$GH_REPO_NAME.git" - # Create a clean working directory for this script. +mkdir code_docs +cd code_docs + # Get the current gh-pages branch -mkdir docs -cd docs -git clone -b gh-pages https://git@$GH_REPO_REF html -cd html +git clone -b gh-pages https://git@$GH_REPO_REF +cd $GH_REPO_NAME ##### Configure git. # Set the push default to simple i.e. push only the current branch. @@ -73,7 +71,6 @@ echo "" > .nojekyll ##### Generate the Doxygen code documentation and log the output. ##### echo 'Generating Doxygen code documentation...' # Redirect both stderr and stdout to the log file AND the console. -cd .. doxygen $DOXYFILE 2>&1 | tee doxygen.log ################################################################################ @@ -83,7 +80,6 @@ doxygen $DOXYFILE 2>&1 | tee doxygen.log # both exist. This is a good indication that Doxygen did it's work. if [ -d "html" ] && [ -f "html/index.html" ]; then - cd html echo 'Uploading documentation to the gh-pages branch...' # Add everything in this directory (the Doxygen code documentation) to the # gh-pages branch. From f764c8174273b4e17f53642be4fe336c9724b024 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 26 Mar 2019 20:14:16 +0100 Subject: [PATCH 007/250] fix build_docs --- .ci/build_docs.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci/build_docs.sh b/.ci/build_docs.sh index 6fff86cd0f4..c16e90720c7 100644 --- a/.ci/build_docs.sh +++ b/.ci/build_docs.sh @@ -71,7 +71,8 @@ echo "" > .nojekyll ##### Generate the Doxygen code documentation and log the output. ##### echo 'Generating Doxygen code documentation...' # Redirect both stderr and stdout to the log file AND the console. -doxygen $DOXYFILE 2>&1 | tee doxygen.log +cd doc +doxygen doxyfile 2>&1 | tee doxygen.log ################################################################################ ##### Upload the documentation to the gh-pages branch of the repository. ##### From 30c85eb944794eaa61106f9e7ad95fe3a805f6ba Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 26 Mar 2019 20:23:11 +0100 Subject: [PATCH 008/250] fix build_docs --- .ci/build_docs.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.ci/build_docs.sh b/.ci/build_docs.sh index c16e90720c7..5becb8a15f3 100644 --- a/.ci/build_docs.sh +++ b/.ci/build_docs.sh @@ -71,8 +71,9 @@ echo "" > .nojekyll ##### Generate the Doxygen code documentation and log the output. ##### echo 'Generating Doxygen code documentation...' # Redirect both stderr and stdout to the log file AND the console. -cd doc -doxygen doxyfile 2>&1 | tee doxygen.log +cp -r $(dirname $DOXYFILE/*) . + +doxygen $DOXYFILE 2>&1 | tee doxygen.log ################################################################################ ##### Upload the documentation to the gh-pages branch of the repository. ##### From 27831613a36caa9ae9065e7ce36273b32551607a Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 26 Mar 2019 20:27:04 +0100 Subject: [PATCH 009/250] Update build_docs.sh --- .ci/build_docs.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.ci/build_docs.sh b/.ci/build_docs.sh index 5becb8a15f3..b477d96a21b 100644 --- a/.ci/build_docs.sh +++ b/.ci/build_docs.sh @@ -71,7 +71,9 @@ echo "" > .nojekyll ##### Generate the Doxygen code documentation and log the output. ##### echo 'Generating Doxygen code documentation...' # Redirect both stderr and stdout to the log file AND the console. -cp -r $(dirname $DOXYFILE/*) . +cp -r $(dirname $DOXYFILE)/* . +pwd +ls doxygen $DOXYFILE 2>&1 | tee doxygen.log From 88a157333466c29df3d322b20bf519936e2f0786 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 26 Mar 2019 20:32:30 +0100 Subject: [PATCH 010/250] Update doxyfile --- doc/doxyfile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/doxyfile b/doc/doxyfile index 851d07e57da..157cb45e893 100644 --- a/doc/doxyfile +++ b/doc/doxyfile @@ -36,11 +36,12 @@ PROJECT_NAME = "AmpGen" PROJECT_NUMBER = 1.1 PROJECT_BRIEF = PROJECT_LOGO = "figs/logo_small.png" -OUTPUT_DIRECTORY = "../build/" +# OUTPUT_DIRECTORY = "../build/" LAYOUT_FILE = "DoxygenLayout.xml" HTML_EXTRA_STYLESHEET = "customdoxygen.css" -INPUT = "../AmpGen" "../README.md" -USE_MDFILE_AS_MAINPAGE = "../README.md" +INPUT = "../AmpGen" +# "../README.md" +# USE_MDFILE_AS_MAINPAGE = "../README.md" IMAGE_PATH = "figs/" # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- From 1eff5dc14229373d8db513cd6a2d68fc03276480 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 26 Mar 2019 20:55:25 +0100 Subject: [PATCH 011/250] Update build_docs.sh --- .ci/build_docs.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/build_docs.sh b/.ci/build_docs.sh index b477d96a21b..3ae1cff4ade 100644 --- a/.ci/build_docs.sh +++ b/.ci/build_docs.sh @@ -85,6 +85,7 @@ doxygen $DOXYFILE 2>&1 | tee doxygen.log if [ -d "html" ] && [ -f "html/index.html" ]; then echo 'Uploading documentation to the gh-pages branch...' + cd html # Add everything in this directory (the Doxygen code documentation) to the # gh-pages branch. # GitHub is smart enough to know which files have changed and which files have From bd62d49e122039b682538376a4722d228a5bad21 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 26 Mar 2019 21:00:40 +0100 Subject: [PATCH 012/250] Update build_docs.sh --- .ci/build_docs.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.ci/build_docs.sh b/.ci/build_docs.sh index 3ae1cff4ade..7c1a03e3681 100644 --- a/.ci/build_docs.sh +++ b/.ci/build_docs.sh @@ -82,10 +82,11 @@ doxygen $DOXYFILE 2>&1 | tee doxygen.log # Only upload if Doxygen successfully created the documentation. # Check this by verifying that the html directory and the file html/index.html # both exist. This is a good indication that Doxygen did it's work. -if [ -d "html" ] && [ -f "html/index.html" ]; then +mv html/* . + +if [ -d "index.html" ]; then echo 'Uploading documentation to the gh-pages branch...' - cd html # Add everything in this directory (the Doxygen code documentation) to the # gh-pages branch. # GitHub is smart enough to know which files have changed and which files have From e2c90911bd5ee1d15915940a563358c940e2cac1 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 26 Mar 2019 21:53:28 +0100 Subject: [PATCH 013/250] Update build_docs.sh --- .ci/build_docs.sh | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/.ci/build_docs.sh b/.ci/build_docs.sh index 7c1a03e3681..1023b84dab5 100644 --- a/.ci/build_docs.sh +++ b/.ci/build_docs.sh @@ -16,8 +16,7 @@ __AUTHOR__="Jeroen de Bruijn" # - TRAVIS_BUILD_NUMBER : The number of the current build. # - TRAVIS_COMMIT : The commit that the current build is testing. # - DOXYFILE : The Doxygen configuration file. -# - GH_REPO_NAME : The name of the repository. -# - GH_REPO_REF : The GitHub reference to the repository. +# - TRAVIS_REPO_SLUG : The username / reponame for the repository. # - GH_REPO_TOKEN : Secure token to the github repository. # # For information on how to encrypt variables for Travis CI please go to @@ -39,13 +38,15 @@ echo 'Setting up the script...' # Exit with nonzero exit code if anything fails set -e -# Create a clean working directory for this script. -mkdir code_docs -cd code_docs +GH_REPO_ORG=`echo $TRAVIS_REPO_SLUG | cut -d "/" -f 1` +GH_REPO_NAME=`echo $TRAVIS_REPO_SLUG | cut -d "/" -f 2` +GH_REPO_REF="github.com/$GH_REPO_ORG/$GH_REPO_NAME.git" +# Create a clean working directory for this script. # Get the current gh-pages branch -git clone -b gh-pages https://git@$GH_REPO_REF -cd $GH_REPO_NAME +cd docs +git clone -b gh-pages https://git@$GH_REPO_REF html +cd html ##### Configure git. # Set the push default to simple i.e. push only the current branch. @@ -71,10 +72,8 @@ echo "" > .nojekyll ##### Generate the Doxygen code documentation and log the output. ##### echo 'Generating Doxygen code documentation...' # Redirect both stderr and stdout to the log file AND the console. -cp -r $(dirname $DOXYFILE)/* . -pwd -ls - +cd .. +cp -r $(dirname $DOXYFILE)/* . doxygen $DOXYFILE 2>&1 | tee doxygen.log ################################################################################ @@ -82,10 +81,9 @@ doxygen $DOXYFILE 2>&1 | tee doxygen.log # Only upload if Doxygen successfully created the documentation. # Check this by verifying that the html directory and the file html/index.html # both exist. This is a good indication that Doxygen did it's work. -mv html/* . - -if [ -d "index.html" ]; then +if [ -d "html" ] && [ -f "html/index.html" ]; then + cd html echo 'Uploading documentation to the gh-pages branch...' # Add everything in this directory (the Doxygen code documentation) to the # gh-pages branch. From 5ea6d9c6d03414a39c1a422cf8bf67400006bdbf Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 26 Mar 2019 21:58:49 +0100 Subject: [PATCH 014/250] Update build_docs.sh --- .ci/build_docs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/build_docs.sh b/.ci/build_docs.sh index 1023b84dab5..573b09d1cf4 100644 --- a/.ci/build_docs.sh +++ b/.ci/build_docs.sh @@ -44,7 +44,7 @@ GH_REPO_REF="github.com/$GH_REPO_ORG/$GH_REPO_NAME.git" # Create a clean working directory for this script. # Get the current gh-pages branch -cd docs +cd doc git clone -b gh-pages https://git@$GH_REPO_REF html cd html From 3eb9286948a0615789e65a3c8fc08305571d2737 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 26 Mar 2019 22:01:10 +0100 Subject: [PATCH 015/250] Update build_docs.sh --- .ci/build_docs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/build_docs.sh b/.ci/build_docs.sh index 573b09d1cf4..f87bc4688ed 100644 --- a/.ci/build_docs.sh +++ b/.ci/build_docs.sh @@ -73,7 +73,7 @@ echo "" > .nojekyll echo 'Generating Doxygen code documentation...' # Redirect both stderr and stdout to the log file AND the console. cd .. -cp -r $(dirname $DOXYFILE)/* . +# cp -r $(dirname $DOXYFILE)/* . doxygen $DOXYFILE 2>&1 | tee doxygen.log ################################################################################ From eb29640c9aa75c670e06afec5ff79e96afc0fa37 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 26 Mar 2019 22:07:13 +0100 Subject: [PATCH 016/250] Update doxyfile --- doc/doxyfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/doxyfile b/doc/doxyfile index 157cb45e893..ee7bd515c95 100644 --- a/doc/doxyfile +++ b/doc/doxyfile @@ -39,9 +39,8 @@ PROJECT_LOGO = "figs/logo_small.png" # OUTPUT_DIRECTORY = "../build/" LAYOUT_FILE = "DoxygenLayout.xml" HTML_EXTRA_STYLESHEET = "customdoxygen.css" -INPUT = "../AmpGen" -# "../README.md" -# USE_MDFILE_AS_MAINPAGE = "../README.md" +INPUT = "../AmpGen" "../README.md" +USE_MDFILE_AS_MAINPAGE = "../README.md" IMAGE_PATH = "figs/" # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- From 8365aba15667a8511133c92f3ffb01bc7548cc57 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 26 Mar 2019 22:11:12 +0100 Subject: [PATCH 017/250] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d6277d15b6e..83819be7a15 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Source code for the evaluation of amplitudes is dynamically generated by a custo * [Applications](#applications) * [Examples](#examples) * [Advanced](#advanced) -* [API documentation](https://tevans1260.gitlab.io/AmpGen/) +* [API documentation](https://goofit.github.io/AmpGen/) * [Acknowledgements](#acknowledgements) ## Getting started @@ -20,7 +20,7 @@ Source code for the evaluation of amplitudes is dynamically generated by a custo #### Getting the source Clone with git ``` -git clone http://gitlab.com/tevans1260/AmpGen.git --recursive +git clone http://github.com/GooFit/AmpGen/ --recursive ``` There is at the time of writing only a master branch (FIXME) From f1680457a5a2c950746f5e8f466b0ecb4ba7a9d4 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 26 Mar 2019 22:17:13 +0100 Subject: [PATCH 018/250] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 83819be7a15..c1fe1669775 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- +

AmpGen is a library and set of applications for fitting and generating multi-body particle decays using the isobar model. It developed out of the MINT project used in the fitting of three and four-body pseudoscalar decays by the CLEO-c and LHCb colloborations. The library can handle the fitting and generation of a wide variety of final states, including those involving fermions and photons, as well as polarised initial states. @@ -306,9 +306,9 @@ The development of this software has been supported by the National Science Fou

- - - + + +

From b77705590611dc9dbb428eab258a644ad2501db5 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 09:12:40 +0100 Subject: [PATCH 019/250] Remove .gtilab-ci.yml, start LASS documentation --- .gitlab-ci.yml | 20 -------------------- AmpGen/Lineshapes.h | 8 ++++++-- doc/doxyfile | 1 - 3 files changed, 6 insertions(+), 23 deletions(-) delete mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index eada0860293..00000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,20 +0,0 @@ -image: alpine:latest - -pages: - stage: deploy - script: - - apk update && apk add doxygen && apk add graphviz - - apk add ghostscript - - mkdir build - - cd doc - - doxygen doxyfile - - cd ../ - - mv build/html/ public - - cp doc/customdoxygen.css public/ - - mkdir public/figs/ - - cp doc/figs/*.png public/figs/. - artifacts: - paths: - - public - only: - - master diff --git a/AmpGen/Lineshapes.h b/AmpGen/Lineshapes.h index 9d4648251ce..65db6cee353 100644 --- a/AmpGen/Lineshapes.h +++ b/AmpGen/Lineshapes.h @@ -180,7 +180,12 @@ namespace AmpGen */ DECLARE_LINESHAPE( GounarisSakurai ); - /// Description of the \f$ K\pi \f$ S-wave, based on the fits to scattering data. + /** @ingroup Lineshapes class LASS + @brief Description of the @f$ K\pi @f$ S-wave, based on the fits to scattering data. + The LASS parameterisation of the @$$ K\pi@$f S-wave is derived from fits to ~ elastic @f$ K \pi @f$ scattering data, which is approximately up to the $f@ K \eta^\prime $f@ threshold. + In this regime, unitarity implies that phases, rather than amplitudes should be summed. In this context, a slow varying nonresonant phases is summed with the phase of a Breit-Wigner, + corresponding to the @f$ K_0*(1430) @f$. + */ DECLARE_LINESHAPE( LASS ); /** @ingroup Lineshapes class Flatte @@ -343,6 +348,5 @@ namespace AmpGen Expression width( const Expression& s, const Expression& s1, const Expression& s2, const Expression& mass, const Expression& width, const Expression& radius, unsigned int L, DebugSymbols* dbexpressions = nullptr ); - } // namespace AmpGen #endif diff --git a/doc/doxyfile b/doc/doxyfile index 851d07e57da..3d918f6044f 100644 --- a/doc/doxyfile +++ b/doc/doxyfile @@ -36,7 +36,6 @@ PROJECT_NAME = "AmpGen" PROJECT_NUMBER = 1.1 PROJECT_BRIEF = PROJECT_LOGO = "figs/logo_small.png" -OUTPUT_DIRECTORY = "../build/" LAYOUT_FILE = "DoxygenLayout.xml" HTML_EXTRA_STYLESHEET = "customdoxygen.css" INPUT = "../AmpGen" "../README.md" From 8a81a46806f9aadb99a3c652d9826fb8e3ef87c9 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 09:21:40 +0100 Subject: [PATCH 020/250] Update doxyfile --- doc/doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/doxyfile b/doc/doxyfile index 3d918f6044f..95330c67c71 100644 --- a/doc/doxyfile +++ b/doc/doxyfile @@ -82,7 +82,7 @@ OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO EXTENSION_MAPPING = -MARKDOWN_SUPPORT = YES +MARKDOWN_SUPPORT = NO AUTOLINK_SUPPORT = YES BUILTIN_STL_SUPPORT = YES CPP_CLI_SUPPORT = NO From 46491bba818894bf9246c8f3375aef84c613c608 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 09:32:07 +0100 Subject: [PATCH 021/250] Update build_docs.sh --- .ci/build_docs.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.ci/build_docs.sh b/.ci/build_docs.sh index f87bc4688ed..35d6588bb29 100644 --- a/.ci/build_docs.sh +++ b/.ci/build_docs.sh @@ -73,7 +73,9 @@ echo "" > .nojekyll echo 'Generating Doxygen code documentation...' # Redirect both stderr and stdout to the log file AND the console. cd .. -# cp -r $(dirname $DOXYFILE)/* . + +doxygen --version + doxygen $DOXYFILE 2>&1 | tee doxygen.log ################################################################################ From 6cabf4d62209192a70bb950e6d4178c2f1ed0c7d Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 10:10:57 +0100 Subject: [PATCH 022/250] Update .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index bc71785599c..c0156f9c0b1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ # This will run on Travis' 'new' container-based infrastructure sudo: false +dist: trusty # Blacklist branches: From e68f62c4486ee350471e2edc0232d133c896b3da Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 11:42:48 +0100 Subject: [PATCH 023/250] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c0156f9c0b1..997b7227bd1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ # This will run on Travis' 'new' container-based infrastructure sudo: false -dist: trusty +dist: xenial # Blacklist branches: From e62caf8671564f8efb6eb97cf02865e3596b8d70 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 11:52:21 +0100 Subject: [PATCH 024/250] add travis CI build --- .ci/build_root.sh | 15 +++++++++++++++ .ci/travis.sh | 17 +++++++++++++++++ .travis.yml | 11 +++++++++-- 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 .ci/build_root.sh create mode 100644 .ci/travis.sh diff --git a/.ci/build_root.sh b/.ci/build_root.sh new file mode 100644 index 00000000000..b930f523ee6 --- /dev/null +++ b/.ci/build_root.sh @@ -0,0 +1,15 @@ +set -evx + +pushd "${DEPS_DIR}" +ROOT_URL="https://root.cern.ch/download/root_v6.16.00.Linux-ubuntu16-x86_64-gcc5.4.tar.gz" + +if [[ ! -f "${DEPS_DIR}/root/bin/root-config" ]] ; then + echo "Downloading Root" + mkdir -p root + travis_retry wget --no-check-certificate --quiet -O - "${ROOT_URL}" | tar --strip-components=1 -xz -C root +fi + +source "${DEPS_DIR}/root/bin/thisroot.sh" +popd + +set +evx diff --git a/.ci/travis.sh b/.ci/travis.sh new file mode 100644 index 00000000000..93dcfcad37a --- /dev/null +++ b/.ci/travis.sh @@ -0,0 +1,17 @@ +echo -en 'travis_fold:start:script.build\\r' +echo "Building..." +set -evx + +mkdir -p build +cd build +cmake .. +cmake --build . -- -j2 + +set +evx +echo -e 'travis_fold:end:script.build\\r' +echo -en 'travis_fold:start:script.test\\r' +echo "Testing..." +set -evx + +ctest --output-on-failure + diff --git a/.travis.yml b/.travis.yml index bc71785599c..79f18bc030b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,13 @@ # This will run on Travis' 'new' container-based infrastructure sudo: false +cache: + ccache: true + apt: true + directories: + - "${TRAVIS_BUILD_DIR}/deps/root" + - "${TRAVIS_BUILD_DIR}/deps/doxygen" + # Blacklist branches: except: @@ -19,13 +26,13 @@ addons: packages: - doxygen - doxygen-doc -# - doxygen-latex - doxygen-gui - graphviz # Build your code e.g. by calling make script: - - echo true + - chmod +x .ci/travis.sh + - source .ci/travis.sh # Generate and deploy documentation after_success: From 5a97e04539e44cf767a2ed9545eae529ce6492ee Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 11:53:54 +0100 Subject: [PATCH 025/250] add travis CI build --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 79f18bc030b..235f533b1cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ # This will run on Travis' 'new' container-based infrastructure sudo: false +dist: xenial cache: ccache: true From bec2bbab5ed317a996ca706cfba627e7a2703ca5 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 12:00:00 +0100 Subject: [PATCH 026/250] Update .travis.yml --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 235f533b1cb..a892583fa21 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,12 +29,17 @@ addons: - doxygen-doc - doxygen-gui - graphviz + +before_install: +- source .ci/build_root.sh # Build your code e.g. by calling make script: - chmod +x .ci/travis.sh - source .ci/travis.sh + + # Generate and deploy documentation after_success: - chmod +x .ci/build_docs.sh From 2de0ec757fbd0e1a7ece9bec3a49c8af47b88833 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 12:03:59 +0100 Subject: [PATCH 027/250] Add DEPS_DIR to travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a892583fa21..f9a91c94eb1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,7 @@ env: - GH_REPO_NAME: AmpGen - DOXYFILE: $TRAVIS_BUILD_DIR/doc/doxyfile - GH_REPO_REF: github.com/GooFit/AmpGen.git + - DEPS_DIR: "${TRAVIS_BUILD_DIR}/deps" # Install dependencies addons: From 861239931b2df8b56a0eb66968c93bf8a16de05b Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 13:23:45 +0100 Subject: [PATCH 028/250] Flag to remove OpenMP for travis CI builds --- .ci/travis.sh | 2 +- AmpGen/Integrator.h | 2 +- Standalone.cmake | 39 +++++++++++++++++++++++---------------- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/.ci/travis.sh b/.ci/travis.sh index 93dcfcad37a..c5102c4b726 100644 --- a/.ci/travis.sh +++ b/.ci/travis.sh @@ -4,7 +4,7 @@ set -evx mkdir -p build cd build -cmake .. +cmake .. -DOPEN_MP=0 cmake --build . -- -j2 set +evx diff --git a/AmpGen/Integrator.h b/AmpGen/Integrator.h index b9e4f5b024e..44fc44707cf 100644 --- a/AmpGen/Integrator.h +++ b/AmpGen/Integrator.h @@ -68,7 +68,7 @@ namespace AmpGen { real_t re[NROLL] = {0}; real_t im[NROLL] = {0}; - #pragma omp parallel for reduction( +: re, im ) + #pragma omp parallel for reduction(+: re, im) for ( size_t i = 0; i < m_events->size(); ++i ) { auto& evt = ( *m_events )[i]; real_t w = evt.weight() / evt.genPdf(); diff --git a/Standalone.cmake b/Standalone.cmake index e3b6e0ecad2..a9f9f1fb13d 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -3,11 +3,14 @@ set(AMPGEN_CXX ${CMAKE_CXX_COMPILER} CACHE FILEPATH "This should be the path to file(GLOB_RECURSE AMPGEN_SRC src/*) file(GLOB_RECURSE AMPGEN_HDR AmpGen/*) - if( NOT "${CMAKE_CXX_STANDARD}" ) set(CMAKE_CXX_STANDARD 14) endif() +SET(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") + +message(STATUS "USE_OPENMP = ${USE_OPENMP}") + set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") @@ -32,7 +35,10 @@ if(DEFINED ENV{ROOTSYS}) endif() find_package(ROOT CONFIG REQUIRED COMPONENTS Matrix MathMore MathCore Gpad Tree Graf) -find_package(OpenMP) + +if( USE_OPENMP ) + find_package(OpenMP) +endif() cmake_print_variables(CMAKE_SOURCE_DIR) @@ -73,22 +79,23 @@ endif() target_link_libraries(AmpGen PUBLIC ROOT::Minuit2 ) - -if(OpenMP_FOUND OR OpenMP_CXX_FOUND) - if(NOT TARGET OpenMP::OpenMP_CXX) - add_library(OpenMP::OpenMP_CXX IMPORTED INTERFACE) - set_property(TARGET OpenMP::OpenMP_CXX PROPERTY INTERFACE_COMPILE_OPTIONS ${OpenMP_CXX_FLAGS}) - set_property(TARGET OpenMP::OpenMP_CXX PROPERTY INTERFACE_LINK_LIBRARIES ${OpenMP_CXX_FLAGS}) - if(CMAKE_VERSION VERSION_LESS 3.4) - set_property(TARGET OpenMP::OpenMP_CXX APPEND PROPERTY INTERFACE_LINK_LIBRARIES -pthread) - else() - find_package(Threads REQUIRED) - set_property(TARGET OpenMP::OpenMP_CXX APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads) +if( USE_OPENMP ) + if(OpenMP_FOUND OR OpenMP_CXX_FOUND) + if(NOT TARGET OpenMP::OpenMP_CXX) + add_library(OpenMP::OpenMP_CXX IMPORTED INTERFACE) + set_property(TARGET OpenMP::OpenMP_CXX PROPERTY INTERFACE_COMPILE_OPTIONS ${OpenMP_CXX_FLAGS}) + set_property(TARGET OpenMP::OpenMP_CXX PROPERTY INTERFACE_LINK_LIBRARIES ${OpenMP_CXX_FLAGS}) + if(CMAKE_VERSION VERSION_LESS 3.4) + set_property(TARGET OpenMP::OpenMP_CXX APPEND PROPERTY INTERFACE_LINK_LIBRARIES -pthread) + else() + find_package(Threads REQUIRED) + set_property(TARGET OpenMP::OpenMP_CXX APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads) + endif() endif() + target_link_libraries(AmpGen PUBLIC OpenMP::OpenMP_CXX) + else() + message(STATUS "OpenMP not found for CXX, you might have forgotten lb-run ROOT bash or CXX=`which g++` in CERN stack") endif() - target_link_libraries(AmpGen PUBLIC OpenMP::OpenMP_CXX) -else() - message(STATUS "OpenMP not found for CXX, you might have forgotten lb-run ROOT bash or CXX=`which g++` in CERN stack") endif() # Default to XROOTD only if on CMT system. Can be overridden with -DAMPGEN_XROOTD=ON From bcff46a5f12a818aa335d0d67a1b154b8c4e41e3 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 13:26:44 +0100 Subject: [PATCH 029/250] Flag to remove OpenMP for travis CI builds --- .ci/travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/travis.sh b/.ci/travis.sh index c5102c4b726..f43327a3484 100644 --- a/.ci/travis.sh +++ b/.ci/travis.sh @@ -4,7 +4,7 @@ set -evx mkdir -p build cd build -cmake .. -DOPEN_MP=0 +cmake .. -DUSE_OPENMP=0 cmake --build . -- -j2 set +evx From f47cfeda9b84f3b516f9a79c2c21ed1874bf41cd Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 13:35:38 +0100 Subject: [PATCH 030/250] minor fix to RecursivePhaseSpace for gcc5.4 --- src/RecursivePhaseSpace.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RecursivePhaseSpace.cpp b/src/RecursivePhaseSpace.cpp index 97d7da88160..a43657b3cb7 100644 --- a/src/RecursivePhaseSpace.cpp +++ b/src/RecursivePhaseSpace.cpp @@ -60,7 +60,7 @@ AmpGen::Event RecursivePhaseSpace::makeEvent( const size_t& cacheSize ) } else { auto evtTmp = segment.decayProds->makeEvent(cacheSize); double v = sqrt( px * px + py * py + pz * pz ) / pE; - boost( evtTmp, {px, py, pz}, v ); + boost( evtTmp, std::tuple(px, py, pz), v ); for(size_t j = 0; j < rt.size(); ++j) rt[j] += evtTmp[j]; } evt.setGenPdf(1); From 41da25dc59a59747d2f14bb7447b516a1c0db7ab Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 13:53:58 +0100 Subject: [PATCH 031/250] add libtbb to .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index f9a91c94eb1..0c853135354 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,7 @@ addons: - doxygen-doc - doxygen-gui - graphviz + - libtbb before_install: - source .ci/build_root.sh From acbfa0a7b761188843665986379df3c3bc986249 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 13:56:55 +0100 Subject: [PATCH 032/250] add libtbb to .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0c853135354..2b9d88c5e92 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ addons: - doxygen-doc - doxygen-gui - graphviz - - libtbb + - libtbb-dev before_install: - source .ci/build_root.sh From 16d05fd3d59e1302b32360f8df5bc2e023044d5e Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 14:19:03 +0100 Subject: [PATCH 033/250] Add libtbb to link options --- Standalone.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Standalone.cmake b/Standalone.cmake index a9f9f1fb13d..de7da148eab 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -129,6 +129,8 @@ target_compile_options(AmpGen -Woverloaded-virtual $<$:-Ofast>) +target_link_libraries(AmpGen PUBLIC "tbb") + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -lstdc++") else() From eb7733a9e850b41bd45f3f7be77f5d94d0fabbeb Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 14:45:36 +0100 Subject: [PATCH 034/250] Update build_root.sh --- .ci/build_root.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.ci/build_root.sh b/.ci/build_root.sh index b930f523ee6..6f7612e3a7c 100644 --- a/.ci/build_root.sh +++ b/.ci/build_root.sh @@ -1,7 +1,9 @@ set -evx pushd "${DEPS_DIR}" -ROOT_URL="https://root.cern.ch/download/root_v6.16.00.Linux-ubuntu16-x86_64-gcc5.4.tar.gz" + +# root_v6.12.06.Linux-ubuntu16-x86_64-gcc5.4.tar.gz +ROOT_URL="https://root.cern.ch/download/root_v6.12.06.Linux-ubuntu16-x86_64-gcc5.4.tar.gz" if [[ ! -f "${DEPS_DIR}/root/bin/root-config" ]] ; then echo "Downloading Root" From 3587b91acc7ab23714dd26ff95f070cec3961d6e Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 15:02:41 +0100 Subject: [PATCH 035/250] Add generator test to travis.sh --- .ci/travis.sh | 16 +++++++++++----- .travis.yml | 2 -- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.ci/travis.sh b/.ci/travis.sh index f43327a3484..3a290477196 100644 --- a/.ci/travis.sh +++ b/.ci/travis.sh @@ -8,10 +8,16 @@ cmake .. -DUSE_OPENMP=0 cmake --build . -- -j2 set +evx -echo -e 'travis_fold:end:script.build\\r' -echo -en 'travis_fold:start:script.test\\r' -echo "Testing..." -set -evx -ctest --output-on-failure +cd .. + +./build/bin/Generator options/example_b2kstarll.opt --nEvents 1000 + + +# echo -e 'travis_fold:end:script.build\\r' +# echo -en 'travis_fold:start:script.test\\r' +# echo "Testing..." +# set -evx + +# ctest --output-on-failure diff --git a/.travis.yml b/.travis.yml index 2b9d88c5e92..0eae7442760 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,8 +40,6 @@ script: - chmod +x .ci/travis.sh - source .ci/travis.sh - - # Generate and deploy documentation after_success: - chmod +x .ci/build_docs.sh From 15ab4d059ebbbe1fcdd7e1b3680d27ccb5346c31 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 16:00:25 +0100 Subject: [PATCH 036/250] Add verbose flag to test --- .ci/travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/travis.sh b/.ci/travis.sh index 3a290477196..17a9ddedce0 100644 --- a/.ci/travis.sh +++ b/.ci/travis.sh @@ -11,7 +11,7 @@ set +evx cd .. -./build/bin/Generator options/example_b2kstarll.opt --nEvents 1000 +./build/bin/Generator options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 1000 # echo -e 'travis_fold:end:script.build\\r' From 64d096c26749e884bd117ef3e0606c4487ff5c1f Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 27 Mar 2019 16:48:26 +0100 Subject: [PATCH 037/250] change abs -> std::abs so compiler phase works on g++5 --- src/UnaryExpression.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/UnaryExpression.cpp b/src/UnaryExpression.cpp index 705b50a16e8..efbfebdaeef 100644 --- a/src/UnaryExpression.cpp +++ b/src/UnaryExpression.cpp @@ -16,7 +16,7 @@ T rsqrt( const T& arg ){ return 1. / sqrt(arg) ; } DEFINE_UNARY_OPERATOR( Log , log ) DEFINE_UNARY_OPERATOR( Sqrt, sqrt ) DEFINE_UNARY_OPERATOR( Exp , exp ) -DEFINE_UNARY_OPERATOR( Abs , abs ) +DEFINE_UNARY_OPERATOR( Abs , std::abs ) DEFINE_UNARY_OPERATOR( Sin , sin ) DEFINE_UNARY_OPERATOR( Cos , cos ) DEFINE_UNARY_OPERATOR( Tan , tan ) From 3473ac12936b16f875df364fee3f813dac96a208 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 28 Mar 2019 15:41:30 +0100 Subject: [PATCH 038/250] Big improvements in CUDA code generation --- .travis.yml | 90 ++++++++++++++++++++--------------------- README.md | 3 +- src/ASTResolver.cpp | 9 +++-- src/CoherentSum.cpp | 2 + src/Expression.cpp | 5 ++- src/UnaryExpression.cpp | 3 +- 6 files changed, 58 insertions(+), 54 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0eae7442760..aee0fdfbbd5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,46 +1,46 @@ # This will run on Travis' 'new' container-based infrastructure -sudo: false -dist: xenial - -cache: - ccache: true - apt: true - directories: - - "${TRAVIS_BUILD_DIR}/deps/root" - - "${TRAVIS_BUILD_DIR}/deps/doxygen" - -# Blacklist -branches: - except: - - gh-pages - -# Environment variables -env: - global: - - GH_REPO_NAME: AmpGen - - DOXYFILE: $TRAVIS_BUILD_DIR/doc/doxyfile - - GH_REPO_REF: github.com/GooFit/AmpGen.git - - DEPS_DIR: "${TRAVIS_BUILD_DIR}/deps" - -# Install dependencies -addons: - apt: - packages: - - doxygen - - doxygen-doc - - doxygen-gui - - graphviz - - libtbb-dev - -before_install: -- source .ci/build_root.sh - -# Build your code e.g. by calling make -script: - - chmod +x .ci/travis.sh - - source .ci/travis.sh - -# Generate and deploy documentation -after_success: - - chmod +x .ci/build_docs.sh - - source .ci/build_docs.sh +# sudo: false +# dist: xenial +# +# cache: +# ccache: true +# apt: true +# directories: +# - "${TRAVIS_BUILD_DIR}/deps/root" +# - "${TRAVIS_BUILD_DIR}/deps/doxygen" +# +# # Blacklist +# branches: +# except: +# - gh-pages +# +# # Environment variables +# env: +# global: +# - GH_REPO_NAME: AmpGen +# - DOXYFILE: $TRAVIS_BUILD_DIR/doc/doxyfile +# - GH_REPO_REF: github.com/GooFit/AmpGen.git +# - DEPS_DIR: "${TRAVIS_BUILD_DIR}/deps" +# +# # Install dependencies +# addons: +# apt: +# packages: +# - doxygen +# - doxygen-doc +# - doxygen-gui +# - graphviz +# - libtbb-dev +# +# before_install: +# - source .ci/build_root.sh +# +# # Build your code e.g. by calling make +# script: +# - chmod +x .ci/travis.sh +# - source .ci/travis.sh +# +# # Generate and deploy documentation +# after_success: +# - chmod +x .ci/build_docs.sh +# - source .ci/build_docs.sh diff --git a/README.md b/README.md index c1fe1669775..728875f2e56 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,6 @@ Source code for the evaluation of amplitudes is dynamically generated by a custo * [Acknowledgements](#acknowledgements) ## Getting started - ### Installation #### Getting the source Clone with git @@ -121,7 +120,7 @@ D0{K(1)(1270)+,pi-} 0 1 0.1 0 0 K(1)(1270)+{rho(770)0{pi+,pi-},K+} 2 1 0 2 0 0 K(1)(1270)+{K*(892)0{K+,pi-},pi+} 0 1 0.1 0 0 0.1 ``` -The production/decay couplings of the K(1270) resonance are now defined in terms of the coupling to the rho(770),K+ channel, +The production/decay couplings of the $`K_1(1270)^{+}`$ resonance are now defined in terms of the coupling to the $`\rho(770) \K^+`$ channel, which can be useful in making comparisons between different production modes of a resonance. Additional care must be taken in such a case to not introduce redundant degrees of freedom. diff --git a/src/ASTResolver.cpp b/src/ASTResolver.cpp index 0275b1b0bf2..39660b13686 100644 --- a/src/ASTResolver.cpp +++ b/src/ASTResolver.cpp @@ -20,6 +20,7 @@ ASTResolver::ASTResolver(const std::map& evtMap, { enable_cuda = NamedParameter("UseCUDA",false); enable_compileTimeConstants = NamedParameter("ASTResolver::CompileTimeConstants",false); + INFO("Flags: " << enableCuda() << " " << enableCompileConstants() ); } bool ASTResolver::hasSubExpressions() const @@ -99,13 +100,13 @@ template <> void ASTResolver::resolve( const Parameter& parameter ) if( enable_cuda ) { size_t t = res->second; std::string it = ""; - if( t % 3 == 0 ) it = "x"; - if( t % 3 == 1 ) it = "y"; - if( t % 3 == 2 ) it = "z"; + if( t % 3 == 0 ) it = ".x"; + if( t % 3 == 1 ) it = ".y"; + if( t % 3 == 2 ) it = ".z"; int stg = t/3; std::string nTimesStg = "+"+std::to_string(stg) +"*N"; if( stg == 0 ) nTimesStg = ""; - if( stg == 1 ) nTimesStg = "N"; + if( stg == 1 ) nTimesStg = "+N"; addResolvedParameter( ¶meter, "x1[i"+nTimesStg+"]" +it ); } else { diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 6acaf88989b..c69ac5b3d52 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -61,6 +61,8 @@ void CoherentSum::addMatrixElement( std::pair& parti if ( name == mE.decayTree.uniqueString() ) return; } m_matrixElements.emplace_back(protoParticle, coupling, mps, m_evtType.getEventFormat(), m_dbThis); + m_matrixElements.rbegin()->pdf.print(); + } void CoherentSum::prepare() diff --git a/src/Expression.cpp b/src/Expression.cpp index 0b11d8ca339..b27342a22f2 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -54,8 +54,9 @@ std::string Constant::to_string(const ASTResolver* resolver) const { return str; }; std::string complex_type_string = resolver != nullptr && resolver->enableCuda() ? "ampgen_cuda::complex_t" : typeof() ; - return std::imag( m_value ) == 0 ? "(" + rounded_string(std::real(m_value)) +")" : - complex_type_string +"("+rounded_string(std::real(m_value))+","+rounded_string(std::imag(m_value))+")"; + std::string literalSuffix = resolver != nullptr && resolver->enableCuda() ? "f" : ""; + return std::imag(m_value) == 0 ? "(" + rounded_string(std::real(m_value)) +literalSuffix + ")" : + complex_type_string +"("+rounded_string(std::real(m_value))+literalSuffix+","+rounded_string(std::imag(m_value))+literalSuffix+")"; } Expression simplify_constant_addition( const Constant& constant, const Expression& expression ) diff --git a/src/UnaryExpression.cpp b/src/UnaryExpression.cpp index efbfebdaeef..d2d60afa5e9 100644 --- a/src/UnaryExpression.cpp +++ b/src/UnaryExpression.cpp @@ -7,6 +7,7 @@ #include "AmpGen/Expression.h" #include "AmpGen/NamedParameter.h" #include "AmpGen/Types.h" +#include "AmpGen/ASTResolver.h" using namespace AmpGen; @@ -34,7 +35,7 @@ ISqrt::ISqrt( const Expression& expression) : IUnaryExpression(expression) {} ISqrt::operator Expression() const { return Expression( std::make_shared(*this) ) ; } complex_t ISqrt::operator()() const { return 1./sqrt( m_expression() ); } std::string ISqrt::to_string(const ASTResolver* resolver) const { - return NamedParameter("enable_cuda",false) ? + return resolver != nullptr && resolver->enableCuda() ? "rsqrt("+m_expression.to_string(resolver)+")" : "1./sqrt("+m_expression.to_string(resolver)+")" ; } From dfbf3674fc01821a8cb67861b639929a1e899eea Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 28 Mar 2019 16:02:51 +0100 Subject: [PATCH 039/250] Remove LaTeX from README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 728875f2e56..d14a0bda9db 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,7 @@ D0{K(1)(1270)+,pi-} 0 1 0.1 0 0 K(1)(1270)+{rho(770)0{pi+,pi-},K+} 2 1 0 2 0 0 K(1)(1270)+{K*(892)0{K+,pi-},pi+} 0 1 0.1 0 0 0.1 ``` -The production/decay couplings of the $`K_1(1270)^{+}`$ resonance are now defined in terms of the coupling to the $`\rho(770) \K^+`$ channel, +The production/decay couplings of the K(1270) resonance are now defined in terms of the coupling to the rho(770),K+ channel, which can be useful in making comparisons between different production modes of a resonance. Additional care must be taken in such a case to not introduce redundant degrees of freedom. From 2da0b64f144c8f212d68abebe7f0d42bd0ddc76f Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 28 Mar 2019 17:33:13 +0100 Subject: [PATCH 040/250] Uncomment .travis.yml --- .travis.yml | 92 ++++++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/.travis.yml b/.travis.yml index aee0fdfbbd5..fdc65dec8c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,46 +1,46 @@ -# This will run on Travis' 'new' container-based infrastructure -# sudo: false -# dist: xenial -# -# cache: -# ccache: true -# apt: true -# directories: -# - "${TRAVIS_BUILD_DIR}/deps/root" -# - "${TRAVIS_BUILD_DIR}/deps/doxygen" -# -# # Blacklist -# branches: -# except: -# - gh-pages -# -# # Environment variables -# env: -# global: -# - GH_REPO_NAME: AmpGen -# - DOXYFILE: $TRAVIS_BUILD_DIR/doc/doxyfile -# - GH_REPO_REF: github.com/GooFit/AmpGen.git -# - DEPS_DIR: "${TRAVIS_BUILD_DIR}/deps" -# -# # Install dependencies -# addons: -# apt: -# packages: -# - doxygen -# - doxygen-doc -# - doxygen-gui -# - graphviz -# - libtbb-dev -# -# before_install: -# - source .ci/build_root.sh -# -# # Build your code e.g. by calling make -# script: -# - chmod +x .ci/travis.sh -# - source .ci/travis.sh -# -# # Generate and deploy documentation -# after_success: -# - chmod +x .ci/build_docs.sh -# - source .ci/build_docs.sh +This will run on Travis' 'new' container-based infrastructure +sudo: false +dist: xenial + +cache: + ccache: true + apt: true + directories: + - "${TRAVIS_BUILD_DIR}/deps/root" + - "${TRAVIS_BUILD_DIR}/deps/doxygen" + +# Blacklist +branches: + except: + - gh-pages + +# Environment variables +env: + global: + - GH_REPO_NAME: AmpGen + - DOXYFILE: $TRAVIS_BUILD_DIR/doc/doxyfile + - GH_REPO_REF: github.com/GooFit/AmpGen.git + - DEPS_DIR: "${TRAVIS_BUILD_DIR}/deps" + +# Install dependencies +addons: + apt: + packages: + - doxygen + - doxygen-doc + - doxygen-gui + - graphviz + - libtbb-dev + +before_install: +- source .ci/build_root.sh + +# Build your code e.g. by calling make +script: + - chmod +x .ci/travis.sh + - source .ci/travis.sh + +# Generate and deploy documentation +after_success: + - chmod +x .ci/build_docs.sh + - source .ci/build_docs.sh From 7592f3418b3dbe55fdd4f5f1ccfde31022dc1a23 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 28 Mar 2019 17:38:29 +0100 Subject: [PATCH 041/250] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index d14a0bda9db..1db84a94ac9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +[![Build Status][travis-badge]][https://travis-ci.org/GooFit/AmpGen] +[![License: LGPL v3][license-badge]](./LICENSE) +

From c206d8ddac92d92674376569da4fdf12e6e8753c Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 28 Mar 2019 17:40:22 +0100 Subject: [PATCH 042/250] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 1db84a94ac9..578c0f59493 100644 --- a/README.md +++ b/README.md @@ -314,3 +314,6 @@ The development of this software has been supported by the National Science Fou

+[travis-badge]: https://travis-ci.org/GooFit/AmpGen.svg?branch=master +[license-badge]: https://img.shields.io/badge/License-GPL%20v2-blue.svg + From cc7fc627e3c685e496c5eb1edca2217ec2b576dd Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 28 Mar 2019 17:41:19 +0100 Subject: [PATCH 043/250] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 578c0f59493..5ed2a882ed8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status][travis-badge]][https://travis-ci.org/GooFit/AmpGen] +[![Build Status][travis-badge]][travis-link] [![License: LGPL v3][license-badge]](./LICENSE)

@@ -316,4 +316,5 @@ The development of this software has been supported by the National Science Fou [travis-badge]: https://travis-ci.org/GooFit/AmpGen.svg?branch=master [license-badge]: https://img.shields.io/badge/License-GPL%20v2-blue.svg +[travis-link]: https://travis-ci.org/GooFit/AmpGen From 498c2c5e22220b914c2810be6f9b8e3aa3e246c9 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 28 Mar 2019 18:19:57 +0100 Subject: [PATCH 044/250] Fix UseCUDA flag in src/CompiledExpressionBase --- src/CompiledExpressionBase.cpp | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index c4e70d99b86..fb0e8e7e7b2 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -80,31 +80,25 @@ void CompiledExpressionBase::to_stream( std::ostream& stream ) const { if( m_db.size() !=0 ) stream << "#include\n"; stream << "extern \"C\" const char* " << progName() << "_name() { return \"" << m_name << "\"; } \n"; - bool enable_cuda = NamedParameter("EnableCUDA",false); + bool enable_cuda = NamedParameter("UseCUDA",false); - size_t sizeOfStream = 0; + INFO("Enabling CUDA ..."); + + size_t sizeOfStream = 0; if( !enable_cuda ){ // Avoid a warning about std::complex not being C compatible (it is) stream << "#pragma clang diagnostic push\n" << "#pragma clang diagnostic ignored \"-Wreturn-type-c-linkage\"\n"; - stream << "extern \"C\" " << returnTypename() << " " << progName() << "(" << fcnSignature() << "){\n"; addDependentExpressions( stream , sizeOfStream ); - std::string objString = m_obj.to_string(m_resolver); - stream << "return " << objString << ";\n}\n"; + stream << "return " << m_obj.to_string(m_resolver) << ";\n}\n"; } else { - std::string rt_cpp = returnTypename(); - std::string rt_cuda = ""; - if( rt_cpp == "double" || rt_cpp == "float" || rt_cpp == "real_t" ) - rt_cuda = "float* r, const int N"; - if( rt_cpp == "std::complex" || rt_cpp == "std::complex" || rt_cpp == "complex_t" ) - rt_cuda = "ampgen_cuda::complex_t* r, const int N"; + std::string rt_cuda = returnTypename() +"* r, const int N" ; stream << "__global__ void " << progName() << "( " << rt_cuda << ", const float_t* x0, const float3* x1){\n"; stream << " int i = blockIdx.x * blockDim.x + threadIdx.x;\n"; addDependentExpressions( stream, sizeOfStream); - std::string objString = m_obj.to_string(m_resolver); - stream << " r[i] = " << objString << ";\n}\n"; + stream << " r[i] = " << m_obj.to_string(m_resolver) << ";\n}\n"; } if( NamedParameter("IncludePythonBindings", false) == true ){ From 85d9517f5c2d166566ed24db3488f78fe21a334b Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 28 Mar 2019 21:28:01 +0100 Subject: [PATCH 045/250] Remove unnecessary statics in utilities --- AmpGen/Utilities.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AmpGen/Utilities.h b/AmpGen/Utilities.h index 90d8f335854..61355707978 100644 --- a/AmpGen/Utilities.h +++ b/AmpGen/Utilities.h @@ -18,7 +18,7 @@ #include "AmpGen/MetaUtils.h" namespace AmpGen { template - static bool isIn( const std::vector& container, const T& obj ) + bool isIn( const std::vector& container, const T& obj ) { for ( auto& it : container ) if ( obj == it ) return true; @@ -26,7 +26,7 @@ namespace AmpGen { } template - static bool isIn( const std::vector& container, const B& obj, F f ) + bool isIn( const std::vector& container, const B& obj, F f ) { for ( auto& it : container ) if ( f( it, obj ) ) return true; From 3cefae9af192aad69cd6161c3e2af32efe25679c Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 28 Mar 2019 21:39:38 +0100 Subject: [PATCH 046/250] Update .travis.yml --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fdc65dec8c2..02705555df0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,3 @@ -This will run on Travis' 'new' container-based infrastructure sudo: false dist: xenial From 4fc8ffa2a2238ca23bb22a05fe5fb7a2e53feb65 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 29 Mar 2019 13:40:54 +0100 Subject: [PATCH 047/250] Add LASS documentation --- AmpGen/Lineshapes.h | 24 ++++++++++++++++++++++-- doc/doxyfile | 2 +- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/AmpGen/Lineshapes.h b/AmpGen/Lineshapes.h index 65db6cee353..3788c8fc5cb 100644 --- a/AmpGen/Lineshapes.h +++ b/AmpGen/Lineshapes.h @@ -183,8 +183,28 @@ namespace AmpGen /** @ingroup Lineshapes class LASS @brief Description of the @f$ K\pi @f$ S-wave, based on the fits to scattering data. The LASS parameterisation of the @$$ K\pi@$f S-wave is derived from fits to ~ elastic @f$ K \pi @f$ scattering data, which is approximately up to the $f@ K \eta^\prime $f@ threshold. - In this regime, unitarity implies that phases, rather than amplitudes should be summed. In this context, a slow varying nonresonant phases is summed with the phase of a Breit-Wigner, - corresponding to the @f$ K_0*(1430) @f$. + In this regime, unitarity implies that phases, rather than amplitudes should be summed. + In this context, a slow varying nonresonant phase, + @f[ + \tan(\phi_{NR}) = \frac{2 a q}{2 + arq^2}, + @f] + where @f$a, r@f$ are parameters determined from scattering data, is added to the phase shift of a Breit-Wigner, + @f[ + \tan(\phi_{BW}) = \frac{m\Gamma(s)}{m^2 -s }, + @f] + normally associated to the @f$ K^*(1430)^{0} @f$ resonance. + The total amplitude is therefore: + @f[ + \mathcal{A}(s) = \frac{2 a \sqrt{s} }{ 2 + arq^2 - 2iaq} + \frac{2+arq^2 + 2iaq}{2+arq^2 - 2iaq }\mathcal{A}_{BW}(s). + @f] + As this expression somewhat resembles the sum of a Breit-Wigner with a slowly varying nonresonant component, the two parts are sometimes split apart with an additional production amplitude placed on one or the other. These can be accessed separately using the modifiers LASS.BW and LASS.NR. + + Parameter | User name | Description + -----------------------|--------------------------------------|------------------------------------------------------------------------ + @f$m@f$ | particleName_mass | Breit-Wigner mass of the resonant component, defined as energy at which the self-energy of the resonance is purely imaginary (defaults to value in PDG)
+ @f$\Gamma_0@f$ | particleName_width | Breit-Wigner width of the resonant component, defined as the width of resonance at the Breit-Wigner mass
+ @f$a@f$ | LASS::a | Scattering length of the nonresonant component, defaults to @f$2.07\mathrm{G\kern -0.1em eV}^{-1}@f$ + @f$a@f$ | LASS::r | Scattering length of the nonresonant component, defaults to @f$3.32\mathrm{G\kern -0.1em eV}^{-1}@f$ */ DECLARE_LINESHAPE( LASS ); diff --git a/doc/doxyfile b/doc/doxyfile index 95330c67c71..3d918f6044f 100644 --- a/doc/doxyfile +++ b/doc/doxyfile @@ -82,7 +82,7 @@ OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO EXTENSION_MAPPING = -MARKDOWN_SUPPORT = NO +MARKDOWN_SUPPORT = YES AUTOLINK_SUPPORT = YES BUILTIN_STL_SUPPORT = YES CPP_CLI_SUPPORT = NO From 44a6053e4b49678d02f6f91e6a1753908875bb31 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 1 Apr 2019 18:21:46 +0200 Subject: [PATCH 048/250] Add code to perform pade approximations, minor improvements in some interfaces --- AmpGen/ArgumentPack.h | 5 +- AmpGen/Array.h | 7 +- AmpGen/CoupledChannel.h | 6 ++ AmpGen/Expression.h | 2 - AmpGen/FitResult.h | 1 + AmpGen/Lineshapes.h | 70 +++++++------------ AmpGen/MetaUtils.h | 5 +- AmpGen/MinuitParameterSet.h | 54 ++++++-------- AmpGen/Pade.h | 60 ++++++++++++++++ AmpGen/ThreeBodyCalculators.h | 1 - AmpGen/Vertex.h | 63 ++++++++++++----- AmpGen/kMatrix.h | 19 +++++ apps/Fitter.cpp | 7 +- src/ASTResolver.cpp | 5 +- src/CoherentSum.cpp | 13 ++-- src/CompiledExpressionBase.cpp | 12 +--- src/DalitzIntegrator.cpp | 3 +- src/ErrorPropagator.cpp | 5 +- src/Expression.cpp | 10 +-- src/FitResult.cpp | 24 +++---- src/Lineshapes.cpp | 12 ++-- src/Lineshapes/Flatte.cpp | 4 +- src/Minimiser.cpp | 18 ++--- src/MinuitParameterSet.cpp | 124 ++++++++++++++++++--------------- src/Pade.cpp | 0 src/PhaseSpace.cpp | 11 ++- src/PolarisedSum.cpp | 3 - src/ThreeBodyCalculators.cpp | 11 +-- src/Vertex.cpp | 19 +++-- 29 files changed, 322 insertions(+), 252 deletions(-) create mode 100644 AmpGen/Pade.h create mode 100644 src/Pade.cpp diff --git a/AmpGen/ArgumentPack.h b/AmpGen/ArgumentPack.h index 90b66758d0f..8ac69eb9dec 100644 --- a/AmpGen/ArgumentPack.h +++ b/AmpGen/ArgumentPack.h @@ -14,8 +14,9 @@ namespace AmpGen virtual ~IArgument() = default; }; /** @class Argument + @brief Structure to pass "named" parameters to functions. Structure to flexibly pass blocks of "Named" parameters to functions, to - approximate the behaviour of python's named arguments. + approximate the behaviour of Python's named arguments. Typical usage is for constructors with variable arguments, such as to read data from the disk. The interface for the user is typically \code{cpp} @@ -36,7 +37,7 @@ namespace AmpGen auto applySym = args.getArg().val; auto entryList = args.getArg().val; \endcode - @tparam: TYPE type of the argument, such as a string, a number, a bool etc. + @tparam TYPE Type of the argument, such as a string, a number, a bool etc. */ template struct Argument : public IArgument { diff --git a/AmpGen/Array.h b/AmpGen/Array.h index 92aeae0310e..3074ea524cf 100644 --- a/AmpGen/Array.h +++ b/AmpGen/Array.h @@ -15,7 +15,12 @@ namespace AmpGen { class ASTResolver; - + + /** @ingroup ExpressionEngine class Array + @brief Expression for a fixed size array of values. + Expression for an array, i.e. a set of values with an index. + Can be used to return an expression from the array, which is resolved at (second) compile time. + */ class Array : public IExpression { public: diff --git a/AmpGen/CoupledChannel.h b/AmpGen/CoupledChannel.h index e72e1e8a68d..f9837963538 100644 --- a/AmpGen/CoupledChannel.h +++ b/AmpGen/CoupledChannel.h @@ -2,5 +2,11 @@ #include "AmpGen/Particle.h" namespace AmpGen { + + namespace Lineshape { + /** @ingroup Lineshapes class CoupledChannel + @brief Description of a resonance that decays to multiple two and three-body final states. */ + DECLARE_LINESHAPE( CoupledChannel ); + } Expression phaseSpace(const Expression& s, const Particle& p, const size_t& l); } diff --git a/AmpGen/Expression.h b/AmpGen/Expression.h index 9198ff061b8..4171a18111d 100644 --- a/AmpGen/Expression.h +++ b/AmpGen/Expression.h @@ -348,7 +348,6 @@ namespace AmpGen /// @ingroup ExpressionEngine struct ACos /// @brief Unary expression that returns \f$\cos^{-1}(z)\f$ DECLARE_UNARY_OPERATOR( ACos ); - /// @ingroup ExpressionEngine struct ATan /// @brief Unary expression that returns \f$\tan^{-1}(z)\f$ DECLARE_UNARY_OPERATOR( ATan ); @@ -412,7 +411,6 @@ namespace AmpGen Expression exp( const Expression& expression ); Expression log( const Expression& expression ); Expression atan2( const Expression& y, const Expression& x); - } template < class T > bool is( const Expression& expression ){ diff --git a/AmpGen/FitResult.h b/AmpGen/FitResult.h index a518679836c..3098a44d8c8 100644 --- a/AmpGen/FitResult.h +++ b/AmpGen/FitResult.h @@ -64,6 +64,7 @@ namespace AmpGen MinuitParameterSet* MPS() const { return &( *m_mps ); } TMatrixD cov() const { return m_covarianceMatrix; } double cov( const size_t& x, const size_t& y ) const { return m_covarianceMatrix( x, y ); } + double cov( const std::string& x, const std::string& y ) const { return m_covarianceMatrix( m_covMapping.at(x), m_covMapping.at(y) ); } void print() const; diff --git a/AmpGen/Lineshapes.h b/AmpGen/Lineshapes.h index 3788c8fc5cb..72c2119ef49 100644 --- a/AmpGen/Lineshapes.h +++ b/AmpGen/Lineshapes.h @@ -39,7 +39,7 @@ */ #define DECLARE_LINESHAPE( X ) \ - class X : public AmpGen::ILineshape { \ + class X : public AmpGen::Lineshape::Base { \ static std::string _id; \ public: \ X(){ DEBUG("Constructing lineshape") ;} \ @@ -54,7 +54,7 @@ } #define DEFINE_LINESHAPE( X ) \ - REGISTER_WITH_KEY( ILineshape, Lineshape::X, #X, std::string ); \ + REGISTER_WITH_KEY( Lineshape::Base, Lineshape::X, #X, std::string ); \ AmpGen::Expression Lineshape::X::get( const AmpGen::Expression& s, const std::vector& p, \ const std::string& particleName, \ const unsigned int& L, const std::string& lineshapeModifier, \ @@ -67,7 +67,7 @@ AmpGen::DebugSymbols* dbexpressions ) const #define DEFINE_GENERIC_SHAPE( X ) \ - REGISTER_WITH_KEY( ILineshape, Lineshape::X, #X, std::string ); \ + REGISTER_WITH_KEY( Lineshape::Base, Lineshape::X, #X, std::string ); \ AmpGen::Expression Lineshape::X::get( const AmpGen::Expression& s, const AmpGen::Expression& s1, \ const AmpGen::Expression& s2, const std::string& particleName, \ const unsigned int& L, const std::string& lineshapeModifier, \ @@ -79,26 +79,25 @@ namespace AmpGen { - class ILineshape { - public: - virtual ~ILineshape() = default; - virtual Expression get( const Expression& s, const Expression& s1, const Expression& s2, - const std::string& particleName, const unsigned int& L, - const std::string& lineshapeModifier, DebugSymbols* dbexpressions = nullptr ) const = 0; - - virtual Expression get( const Expression& s, const std::vector& p, const std::string& particleName, - const unsigned int& L, const std::string& lineshapeModifier, - AmpGen::DebugSymbols* dbexpressions = nullptr ) const = 0; - ILineshape* create() { return this; } - }; - /** @ingroup Lineshapes namespace Lineshape Namespace that contains all lineshapes, i.e. propagators for describing amplitudes and phases for resonances (and nonresonant) contributions to a total amplitude. */ namespace Lineshape { - class Factory : public AmpGen::Factory + class Base { + public: + virtual ~Base() = default; + virtual Expression get( const Expression& s, const Expression& s1, const Expression& s2, + const std::string& particleName, const unsigned int& L, + const std::string& lineshapeModifier, DebugSymbols* dbexpressions = nullptr ) const = 0; + virtual Expression get( const Expression& s, const std::vector& p, const std::string& particleName, + const unsigned int& L, const std::string& lineshapeModifier, + AmpGen::DebugSymbols* dbexpressions = nullptr ) const = 0; + Base* create() { return this; } + }; + + class Factory : public AmpGen::Factory { public: static Expression get(const std::string& lineshape, const Expression& s, const Expression& s1, @@ -134,7 +133,7 @@ namespace AmpGen @f$r@f$ | particleName_radius | Hadronic radius for Blatt-Weisskopf form-factor (defaults to 1.5GeV for light resonances, 3.5GeV for charm) BL : Use Blatt-Weisskopf factors normalised at @f$ \sqrt{s}=m @f$ (by default, normalised at @f$\sqrt{s}=0@f$) - \image html BW_combined.png "Modulus and phase of the Relativistic Breit-Wigner propagator, for @f$l={0,4}@f$, using the mass and nominal width of the @f$\rho@f$ meson" + \image html BW_combined.png "Modulus and phase of the Relativistic Breit-Wigner propagator, for orbital momentum up-to four, using the mass and nominal width of the rho meson." */ DECLARE_LINESHAPE( BW ); @@ -182,7 +181,7 @@ namespace AmpGen /** @ingroup Lineshapes class LASS @brief Description of the @f$ K\pi @f$ S-wave, based on the fits to scattering data. - The LASS parameterisation of the @$$ K\pi@$f S-wave is derived from fits to ~ elastic @f$ K \pi @f$ scattering data, which is approximately up to the $f@ K \eta^\prime $f@ threshold. + The LASS parameterisation of the @f$ K\pi @f$ S-wave is derived from fits to ~ elastic @f$ K \pi @f$ scattering data, which is approximately up to the @f$ K \eta^\prime @f$ threshold. In this regime, unitarity implies that phases, rather than amplitudes should be summed. In this context, a slow varying nonresonant phase, @f[ @@ -204,7 +203,7 @@ namespace AmpGen @f$m@f$ | particleName_mass | Breit-Wigner mass of the resonant component, defined as energy at which the self-energy of the resonance is purely imaginary (defaults to value in PDG)
@f$\Gamma_0@f$ | particleName_width | Breit-Wigner width of the resonant component, defined as the width of resonance at the Breit-Wigner mass
@f$a@f$ | LASS::a | Scattering length of the nonresonant component, defaults to @f$2.07\mathrm{G\kern -0.1em eV}^{-1}@f$ - @f$a@f$ | LASS::r | Scattering length of the nonresonant component, defaults to @f$3.32\mathrm{G\kern -0.1em eV}^{-1}@f$ + @f$r@f$ | LASS::r | Scattering length of the nonresonant component, defaults to @f$3.32\mathrm{G\kern -0.1em eV}^{-1}@f$ */ DECLARE_LINESHAPE( LASS ); @@ -220,11 +219,11 @@ namespace AmpGen @f] where the running width is given by @f[ - \Gamma(s) = g_{\pi\pi} \left( \Lambda^{1/2}(s,m_{\pi}^2,m_{\pi}^2) + \frac{g_{KK}}{g_{\pi\pi}} \Lambda^{1/2}(s,m_K^2, m_K^2) \right) + \Gamma(s) = \frac{ g_{\pi\pi} }{s} \left( \Lambda^{1/2}(s,m_{\pi}^2,m_{\pi}^2) + \frac{g_{KK}}{g_{\pi\pi}} \Lambda^{1/2}(s,m_K^2, m_K^2) \right) @f] or @f[ - \Gamma(s) = g_{\pi\eta} \left( \Lambda^{1/2}(s,m_{\pi}^2,m_{\eta}^2) + \frac{g_{KK}}{g_{\pi\eta}} \Lambda^{1/2}(s,m_K^2, m_K^2) \right) + \Gamma(s) = \frac{ g_{\pi\eta}}{s} \left( \Lambda^{1/2}(s,m_{\pi}^2,m_{\eta}^2) + \frac{g_{KK}}{g_{\pi\eta}} \Lambda^{1/2}(s,m_K^2, m_K^2) \right) @f] for the @f$f_0(980)^{0}@f$ and the @f$a_0(980)^{0}@f$, respectively. @@ -240,7 +239,7 @@ namespace AmpGen /** @ingroup Lineshapes class Gaussian @brief Gaussian shape for (relatively) long lived states that are limited by experimental resolution, rather than natural width. - @detail The gaussian lineshape has the form + The gaussian lineshape has the form @f[ \mathcal{A}(s) = e^{ -(s-\mu)^2 / 2\sigma^2 }, @f] @@ -258,22 +257,6 @@ namespace AmpGen * @brief Polynominal shape \f$ \mathcal{A}(s) = \sum^n_i c_i s^{i} \f$ where the sum is to lineshapeModifier::Degree, and the free parameters of the shape are lineshapeModifier_ci */ DECLARE_LINESHAPE( Poly ); - - /** @ingroup Lineshapes class kMatrix - @brief Anisovich-Sarantsev Isoscalar K-matrix from https://arxiv.org/abs/hep-ph/0204328 - - Describes the isoscalar @f$ \pi\pi, KK, 4\pi \eta\eta, \eta\eta^\prime@f$ S-wave in terms of a five-by-five K-matrix and corresponding P-vector couplings. - Includes a large number of parameters that can be fixed from the above publication. - These parameters can be found in the options directory, which in turn can be includes in the fit by adding - - \code{cpp} - Import $AMPGENROOT/options/kMatrix.opt - \endcode - - to the user configuration file. - */ - DECLARE_LINESHAPE( kMatrix ); - /** @ingroup Lineshapes class FOCUS * @brief K matrix amplitudes used for I=1/2 and I=3/2 in the description of the \f$ K\pi \f$ S-wave in the analysis of @f$ D^{+}\rightarrow K^{-}\pi^{+}\pi^{+}@f$ https://arxiv.org/abs/0705.2248 */ @@ -283,11 +266,10 @@ namespace AmpGen DECLARE_LINESHAPE( PALANO ); /** @ingroup Lineshapes class ObelixRho - * @brief Amplitude to describe the vector-isovector system, otherwise known as the @f$ \rho @f$ mesons. WARNING untested. + @brief Amplitude to describe the vector-isovector system, otherwise known as the @f$ \rho @f$ mesons. WARNING untested. Vector-Isovector amplitude @f$(I=1, J=1)@f$ using a K-matrix to describe the @f$\pi\pi, KK, \pi\pi\pi\pi @f$ channels using three poles, commonly associated with - the @f$ \rho(770), \rho(1450), \rho(1900) @f$ resonances. - */ + the @f$ \rho(770), \rho(1450), \rho(1900) @f$ resonances.*/ DECLARE_LINESHAPE( ObelixRho ); /// K matrix to describe \f$K_1(1270) / K_1(1400)\f$. WARNING incompleted. @@ -326,10 +308,6 @@ namespace AmpGen DECLARE_LINESHAPE( DecaySpline ); DECLARE_LINESHAPE( InelasticSpline ); - /** @ingroup Lineshapes class CoupledChannel - @brief Description of a resonance that decays to multiple two and three-body final states. - */ - DECLARE_LINESHAPE( CoupledChannel ); /** @ingroup Lineshapes class GenericKmatrix @brief Implementation of a generic K-matrix */ diff --git a/AmpGen/MetaUtils.h b/AmpGen/MetaUtils.h index 4d436d436fb..31985fe437e 100644 --- a/AmpGen/MetaUtils.h +++ b/AmpGen/MetaUtils.h @@ -10,9 +10,10 @@ namespace AmpGen { /** Utility classes for (library) compile-level metaprogramming, such as identifying the types of - * arguments for generating source code, compile-time unrolling of tuples and loops, and identifying if a class can be constructed in different ways. + arguments for generating source code, compile-time unrolling of tuples and loops, + and identifying if a class can be constructed in different ways. */ - + template std::string typeof() { int status = 0; diff --git a/AmpGen/MinuitParameterSet.h b/AmpGen/MinuitParameterSet.h index 272b556c7fc..b726b9334a3 100644 --- a/AmpGen/MinuitParameterSet.h +++ b/AmpGen/MinuitParameterSet.h @@ -17,6 +17,9 @@ namespace AmpGen class MinuitParameterSet { public: + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + MinuitParameterSet(); MinuitParameterSet( const MinuitParameterSet& other ); ~MinuitParameterSet(); @@ -24,28 +27,23 @@ namespace AmpGen MinuitParameterSet getFloating(); bool add( MinuitParameter* parPtr ); - MinuitParameter* add( const std::string& name, const unsigned int& flag, const double& mean, const double& sigma, - const double& min = 0, const double& max = 0 ); + MinuitParameter* add(const std::string& name, const unsigned int& flag, const double& mean, const double& sigma, const double& min = 0, const double& max = 0 ); bool unregister( MinuitParameter* patPtr ); - MinuitParameter* addOrGet( const std::string& name, const unsigned int& flag, const double& mean, - const double& sigma, const double& min = 0, const double& max = 0 ); + MinuitParameter* addOrGet(const std::string& name, const unsigned int& flag, const double& mean, + const double& sigma, const double& min = 0, const double& max = 0 ); void loadFromStream(); void loadFromFile( const std::string& name ); void resetToInit(); unsigned int size() const; - MinuitParameter* getParPtr( unsigned int i ) const; - - std::map& map() { return _keyAccess; } - const std::map& const_map() const { return _keyAccess; } - std::vector::const_iterator cbegin() const { return _parPtrList.cbegin(); } - std::vector::const_iterator cend() const { return _parPtrList.cend(); } - - std::vector parPtrs() { return _parPtrList; } - std::vector::iterator begin() { return _parPtrList.begin(); } - std::vector::iterator end() { return _parPtrList.end(); } - std::vector::const_iterator begin() const { return _parPtrList.cbegin(); } - std::vector::const_iterator end() const { return _parPtrList.cend(); } + std::map& map(); + const std::map& const_map() const; + const_iterator cbegin() const; + const_iterator cend() const; + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; void deleteListAndObjects(); void deleteListKeepObjects(); @@ -55,28 +53,20 @@ namespace AmpGen void set( const MinuitParameterSet& mps ); MinuitParameter* at( const std::string& key ); + MinuitParameter* at( const size_t& index ) const; MinuitParameter* operator[]( const std::string& key ); MinuitParameter* operator[]( const std::string& key ) const; - MinuitParameter* operator[]( const unsigned int& key ); - MinuitParameter* find( const std::string& key ) const - { - auto it = _keyAccess.find(key); - return it == _keyAccess.end() ? nullptr : it->second; - } - double operator()( const std::string& name ) - { - if ( _keyAccess.find( name ) == _keyAccess.end() ) { - std::cout << "Cannot find parameter " << name << std::endl; - } - return _keyAccess[name]->mean(); - } + MinuitParameter* operator[]( const size_t& key ); + MinuitParameter* find( const std::string& key ) const; + double operator()( const std::string& name ); private: void tryParameter( const std::vector& line ); void tryAlias( const std::vector& line ); - std::vector _parPtrList; - std::vector _aliasList; - std::map _keyAccess; bool addToEnd( MinuitParameter* parPtr ); + + std::vector m_parameters; + std::vector m_expressions; + std::map m_keyAccess; }; diff --git a/AmpGen/Pade.h b/AmpGen/Pade.h new file mode 100644 index 00000000000..4e13fa9ca37 --- /dev/null +++ b/AmpGen/Pade.h @@ -0,0 +1,60 @@ +#ifndef AMPGEN_PADE_H +#define AMPGEN_PADE_H + +#include "TMatrixD.h" +#include "TVectorD.h" +#include +#include + +namespace AmpGen { + enum Strategy { linear, quadratic, cubic, quartic }; + template + class Pade { + private: + std::function m_function; + std::array co_f; + std::array co_g; + T min; + T max; + T range; + public: + + Pade(const std::function& fcn, + const double& min, + const double& max, + const Strategy& strat = Strategy::linear) : + m_function(fcn), min(min),max(max){ + TMatrixD solver(2*N+1,2*N+1); + std::vector samples(2*N+1); + if( strat < 4 ){ + for(size_t eq = 0 ; eq < 2*N+1; ++eq) + samples[eq] = pow( eq/double(2*N), strat + 1); + } + TVectorD rest(2*N+1); + for( int eq = 0 ; eq < 2*N+1; ++eq ){ + rest(eq) = fcn( samples[eq]*(max-min) + min); + for(int i = 0; i <= N; ++i) solver(eq,i) = pow(samples[eq],i); + for(int i = 1; i <= N; ++i) solver(eq,i+N) = -rest(eq)* pow(samples[eq],i); + } + solver.Invert(); + auto r = solver * rest; + for(size_t i = 0; i <= N; ++i ) co_f[i] = r[i]; + for(size_t i = 0; i < N; ++i ) co_g[i] = r[i+(N+1)]; + range = 1./(max-min); + } + T operator()(const T& s){ + T x = (s-min)*range; + T f = 0; + T g = 1; + T acc = 1; + for(size_t i = 0; i < N; ++i){ + f += co_f[i] * acc; + acc *= x; + g += co_g[i] * acc; + } + return (f + co_f[N]*acc)/g; + } + }; +} + +#endif diff --git a/AmpGen/ThreeBodyCalculators.h b/AmpGen/ThreeBodyCalculators.h index 4ff024ede6a..887baf2b958 100644 --- a/AmpGen/ThreeBodyCalculators.h +++ b/AmpGen/ThreeBodyCalculators.h @@ -10,7 +10,6 @@ class TGraph; namespace AmpGen { - class MinuitParameterSet; class ThreeBodyCalculator diff --git a/AmpGen/Vertex.h b/AmpGen/Vertex.h index fb2cd7636c3..2f2101c273a 100644 --- a/AmpGen/Vertex.h +++ b/AmpGen/Vertex.h @@ -24,31 +24,31 @@ * Macro to declare a vertex */ #define DECLARE_VERTEX(NAME) \ - struct NAME : public VertexBase { \ + struct NAME : public Base { \ NAME(){ DEBUG("Constructing vertex"); } \ - virtual Tensor operator()( const Tensor& P, const Tensor& Q, const Tensor& V1, const Tensor& V2, DebugSymbols* db = 0 ) override; \ + virtual Tensor operator()(const Tensor& P, const Tensor& Q, const Tensor& V1, const Tensor& V2, DebugSymbols* db = 0 ) override; \ static std::string _id; \ } #define DEFINE_VERTEX(VERTEX) \ - REGISTER_WITH_KEY( Vertex::VertexBase, Vertex::VERTEX, #VERTEX, std::string ); \ + REGISTER_WITH_KEY( Vertex::Base, Vertex::VERTEX, #VERTEX, std::string ); \ Tensor Vertex::VERTEX::operator()( const Tensor& P, const Tensor& Q, const Tensor& V1, const Tensor& V2, DebugSymbols* db ) namespace AmpGen { /** @ingroup Vertices namespace Vertex - Namespace that contains the base class for vertices, VertexBase, as well as the implementations + Namespace that contains the base class for vertices, Vertex::Base, as well as the implementations of specific spin couplings and some helper functions such as the orbital operators. */ namespace Vertex { - /** @ingroup Vertices class VertexBase + /** @ingroup Vertices class Base @brief Base class for all spin vertices. Virtual base class from which all the other vertices derive, in essence this is just a named function pointer that can create a pointer to itself, i.e. such that it can be constructed using a Factory. */ - struct VertexBase { + struct Base { /** Calculate the generalised current for this decay process, as a function of: @param P The momentum of the decaying particle @@ -64,8 +64,8 @@ namespace AmpGen const AmpGen::Tensor& V2, AmpGen::DebugSymbols* db = nullptr ) = 0; - virtual ~VertexBase() = default; - VertexBase* create() { return this; } + virtual ~Base() = default; + Base* create() { return this; } }; /// \ingroup Vertices class S_SS_S /// \brief \f$ S = S_1 S_2 \f$ @@ -153,7 +153,7 @@ namespace AmpGen DECLARE_VERTEX( S_ff_S1 ); DECLARE_VERTEX( V_ff_P ); DECLARE_VERTEX( V_ff_P1 ); - class Factory : public AmpGen::Factory + class Factory : public AmpGen::Factory { public: static Tensor getSpinFactor( const Tensor& P, const Tensor& Q, const Tensor& V1, const Tensor& V2, @@ -164,14 +164,43 @@ namespace AmpGen }; } // namespace Vertex - /// \ingroup Vertices function Orbital_PWave - /// Helper function that computes the L=1 orbital momentum operator, i.e. - /// \f$ L_{\mu} = q_{\mu} - \frac{p_{\nu}q^{\nu} p_{\mu} }{ p_{\alpha} p^{\alpha}} \f$ - Tensor Orbital_PWave( const Tensor& A, const Tensor& B ); - Tensor Orbital_DWave( const Tensor& A, const Tensor& B ); - Tensor Spin1Projector( const Tensor& A ); - Tensor Spin2Projector( const Tensor& A ); - + /** @ingroup Vertices function Orbital_PWave + @brief Helper function that computes the @f$L=1@f$ orbital momentum operator. + Helper function that computes the @f$L=1@f$ orbital momentum operator, which is given by + @f[ L_{\mu} = q_{\mu} - p_{\mu} \frac{p_{\nu}q^{\nu}}{ p^2 }, @f] + where @f$ p @f$ is total momentum and @f$ q @f$ is the momentum difference between + the two particles in the state. + */ + Tensor Orbital_PWave(const Tensor& p, const Tensor& q); + + /** @ingroup Vertices function Orbital_DWave + @brief Helper function that computes the @f$L=2@f$ orbital momentum operator. + Helper function that computes the @f$L=2@f$ orbital momentum operator, which is given by + @f[ L_{\mu\nu} = L_{\mu}L_{\nu} - \frac{L^2}{3} S_{\mu\nu}, @f] + where @f$ L_{\mu} @f$ is the Orbital_PWave operator and @f$ S_{\mu\nu} @f$ is the + Spin1Projector. */ + Tensor Orbital_DWave(const Tensor& p, const Tensor& q); + + /** @ingroup Vertices function Spin1Projector + @brief Helper function that computes the projection operator onto a spin one state. + Helper function that projects some lorentz object onto the momentum @f$p_\mu @f$ of state, + and is given by + @f[ S_{\mu\nu} = g_{\mu\nu} - \frac{p_{\mu}p_{\nu}}{p^2}. @f] */ + Tensor Spin1Projector(const Tensor& p); + + /** @ingroup Vertices function Spin2Projector + @brief Helper function that computes the projection operator onto a spin one state. + Helper function that projects some lorentz object onto the momentum @f$p_\mu @f$ of state, + and is given by + @f[ S_{\mu\nu\alpha\beta} = \frac{1}{2}\left( S_{\mu\alpha} S_{\nu\beta} + S_{\mu\beta}S_{\nu\alpha} \right) - \frac{1}{3} S_{\mu\nu} S_{\alpha\beta}, @f] + where @f$ S_{\mu\nu} @f$ is the spin-one projection operator (see Spin1Projector). */ + Tensor Spin2Projector(const Tensor& p); + + /** @ingroup Vertices function Spin1hProjector + @brief Helper function that projects a spinor. + Helper function that projects out a spin-half state + @f[ S_{ab} = \frac{1}{2m}\left( {p\!\!\!/} + m I \right) @f] + */ Tensor Spin1hProjector( const Tensor& B ); Tensor Spin3hProjector( const Tensor& A ); diff --git a/AmpGen/kMatrix.h b/AmpGen/kMatrix.h index ae4165af1fc..b242b36908b 100644 --- a/AmpGen/kMatrix.h +++ b/AmpGen/kMatrix.h @@ -3,9 +3,28 @@ #include "AmpGen/Expression.h" #include "AmpGen/Tensor.h" +#include "AmpGen/Lineshapes.h" namespace AmpGen { + namespace Lineshape { + + /** @ingroup Lineshapes class kMatrix + @brief Anisovich-Sarantsev Isoscalar K-matrix from https://arxiv.org/abs/hep-ph/0204328 + + Describes the isoscalar @f$ \pi\pi, KK, 4\pi \eta\eta, \eta\eta^\prime@f$ S-wave in terms of a five-by-five K-matrix and corresponding P-vector couplings. + Includes a large number of parameters that can be fixed from the above publication. + These parameters can be found in the options directory, which in turn can be includes in the fit by adding + + \code{cpp} + Import $AMPGENROOT/options/kMatrix.opt + \endcode + + to the user configuration file. + */ + DECLARE_LINESHAPE( kMatrix ); + } + struct poleConfig { Expression s; std::vector couplings; diff --git a/apps/Fitter.cpp b/apps/Fitter.cpp index 406c20071ee..3e8396388ba 100644 --- a/apps/Fitter.cpp +++ b/apps/Fitter.cpp @@ -52,13 +52,12 @@ std::vector threeBodyCalculators( MinuitParameterSet& mps ) void randomizeStartingPoint( MinuitParameterSet& MPS, TRandom3& rand, bool SplineOnly = false ) { double range = 5; - for ( unsigned int i = 0; i < MPS.size(); ++i ) { - auto param = MPS.getParPtr( i ); + for (auto& param : MPS) { if ( param->iFixInit() == 0 ) { if ( SplineOnly && param->name().find( "::Spline::" ) == std::string::npos ) continue; range = param->maxInit() - param->minInit(); - MPS.getParPtr( i )->setInit( range * rand.Rndm() + param->meanInit() ); - MPS.getParPtr( i )->print(); + param->setInit( range * rand.Rndm() + param->meanInit() ); + param->print(); std::cout << std::endl; } } diff --git a/src/ASTResolver.cpp b/src/ASTResolver.cpp index 39660b13686..69a0b644e8e 100644 --- a/src/ASTResolver.cpp +++ b/src/ASTResolver.cpp @@ -19,8 +19,7 @@ ASTResolver::ASTResolver(const std::map& evtMap, nParameters(0) { enable_cuda = NamedParameter("UseCUDA",false); - enable_compileTimeConstants = NamedParameter("ASTResolver::CompileTimeConstants",false); - INFO("Flags: " << enableCuda() << " " << enableCompileConstants() ); + enable_compileTimeConstants = NamedParameter("ASTResolver::CompileTimeConstants", false); } bool ASTResolver::hasSubExpressions() const @@ -119,7 +118,7 @@ template <> void ASTResolver::resolve( const Parameter& parameter ) if( it != nullptr ){ if( enable_compileTimeConstants && it->iFixInit() == MinuitParameter::Flag::CompileTimeConstant ){ - addResolvedParameter( ¶meter, std::to_string(it->mean()) ); + addResolvedParameter( ¶meter, "("+std::to_string(it->mean()) +")" ); } else addResolvedParameter( ¶meter, addCacheFunction( parameter.name(), it ) ); return; diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index c69ac5b3d52..099e7808e45 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -61,8 +61,6 @@ void CoherentSum::addMatrixElement( std::pair& parti if ( name == mE.decayTree.uniqueString() ) return; } m_matrixElements.emplace_back(protoParticle, coupling, mps, m_evtType.getEventFormat(), m_dbThis); - m_matrixElements.rbegin()->pdf.print(); - } void CoherentSum::prepare() @@ -178,7 +176,7 @@ std::vector CoherentSum::fitFractions(const LinearErrorPropagator& return outputFractions; } -void CoherentSum::generateSourceCode( const std::string& fname, const double& normalisation, bool add_mt ) +void CoherentSum::generateSourceCode(const std::string& fname, const double& normalisation, bool add_mt) { std::ofstream stream( fname ); transferParameters(); @@ -188,11 +186,10 @@ void CoherentSum::generateSourceCode( const std::string& fname, const double& no stream << "#include \n"; if ( add_mt ) stream << "#include \n"; bool includePythonBindings = NamedParameter("CoherentSum::IncludePythonBindings",false); - bool enableCuda = NamedParameter("CoherentSum::EnableCuda",false); for ( auto& p : m_matrixElements ){ stream << p.pdf << std::endl; - if( ! enableCuda ) p.pdf.compileWithParameters( stream ); + p.pdf.compileWithParameters( stream ); if( includePythonBindings ) p.pdf.compileDetails( stream ); } Expression event = Parameter("x0",0,true,0); @@ -203,10 +200,8 @@ void CoherentSum::generateSourceCode( const std::string& fname, const double& no Expression this_amplitude = p.coupling() * Function( programatic_name( p.pdf.name() ) + "_wParams", {event} ); amplitude = amplitude + ( p.decayTree.finalStateParity() == 1 ? 1 : pa ) * this_amplitude; } - if( !enableCuda ){ - stream << CompiledExpression< std::complex, const double*, int>( amplitude , "AMP" ) << std::endl; - stream << CompiledExpression< double, const double*, int>(fcn::norm(amplitude) / normalisation, "FCN" ) << std::endl; - } + stream << CompiledExpression< std::complex, const double*, int>( amplitude , "AMP" ) << std::endl; + stream << CompiledExpression< double, const double*, int>(fcn::norm(amplitude) / normalisation, "FCN" ) << std::endl; if( includePythonBindings ){ stream << CompiledExpression< unsigned int >( m_matrixElements.size(), "matrix_elements_n" ) << std::endl; stream << CompiledExpression< double > ( normalisation, "normalization") << std::endl; diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index fb0e8e7e7b2..e6dc28c1dad 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -70,7 +70,7 @@ void CompiledExpressionBase::prepare() void CompiledExpressionBase::addDependentExpressions( std::ostream& stream, size_t& sizeOfStream ) const { for ( auto& dep : m_dependentSubexpressions ) { - std::string rt = "auto v" + std::to_string(dep.first) + " = " + dep.second.to_string(m_resolver) +";"; + std::string rt = " auto v" + std::to_string(dep.first) + " = " + dep.second.to_string(m_resolver) +";"; stream << rt << "\n"; sizeOfStream += sizeof(char) * rt.size(); /// bytes /// } @@ -81,21 +81,15 @@ void CompiledExpressionBase::to_stream( std::ostream& stream ) const if( m_db.size() !=0 ) stream << "#include\n"; stream << "extern \"C\" const char* " << progName() << "_name() { return \"" << m_name << "\"; } \n"; bool enable_cuda = NamedParameter("UseCUDA",false); - - INFO("Enabling CUDA ..."); - size_t sizeOfStream = 0; if( !enable_cuda ){ - // Avoid a warning about std::complex not being C compatible (it is) - stream << "#pragma clang diagnostic push\n" - << "#pragma clang diagnostic ignored \"-Wreturn-type-c-linkage\"\n"; + stream << "#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wreturn-type-c-linkage\"\n"; stream << "extern \"C\" " << returnTypename() << " " << progName() << "(" << fcnSignature() << "){\n"; addDependentExpressions( stream , sizeOfStream ); stream << "return " << m_obj.to_string(m_resolver) << ";\n}\n"; } else { - std::string rt_cuda = returnTypename() +"* r, const int N" ; - stream << "__global__ void " << progName() << "( " << rt_cuda << ", const float_t* x0, const float3* x1){\n"; + stream << "__global__ void " << progName() << "( " << returnTypename() + "* r, const int N, " << fcnSignature() << "){\n"; stream << " int i = blockIdx.x * blockDim.x + threadIdx.x;\n"; addDependentExpressions( stream, sizeOfStream); stream << " r[i] = " << m_obj.to_string(m_resolver) << ";\n}\n"; diff --git a/src/DalitzIntegrator.cpp b/src/DalitzIntegrator.cpp index e06568ba8f2..6c7d7ac02fb 100644 --- a/src/DalitzIntegrator.cpp +++ b/src/DalitzIntegrator.cpp @@ -191,6 +191,5 @@ double DalitzIntegrator::integrate_internal( TF2& fcn ) const ig.SetRelTolerance( 0.000001 ); double xmin[] = {0, 0}; double xmax[] = {1, 1}; - double v = ig.Integral( xmin, xmax ); - return v ; + return ig.Integral(xmin,xmax); } diff --git a/src/ErrorPropagator.cpp b/src/ErrorPropagator.cpp index 3c62fdbb804..38cf12fb436 100644 --- a/src/ErrorPropagator.cpp +++ b/src/ErrorPropagator.cpp @@ -70,11 +70,10 @@ LinearErrorPropagator::LinearErrorPropagator( const std::vectoriFixInit() != MinuitParameter::Float ) continue; if( param->err() == 0 ) continue; - m_parameters.push_back( param ); + m_parameters.push_back(param); } m_cov.ResizeTo( m_parameters.size(), m_parameters.size() ); for( size_t i = 0 ; i < m_parameters.size(); ++i ) diff --git a/src/Expression.cpp b/src/Expression.cpp index b27342a22f2..6ad9d69f368 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -18,11 +18,11 @@ using namespace AmpGen; -DEFINE_CAST( Constant ) -DEFINE_CAST( Parameter ) -DEFINE_CAST( SubTree ) -DEFINE_CAST( Ternary ) -DEFINE_CAST( Function ) +DEFINE_CAST(Constant ) +DEFINE_CAST(Parameter ) +DEFINE_CAST(SubTree ) +DEFINE_CAST(Ternary ) +DEFINE_CAST(Function ) Expression::Expression( const std::shared_ptr& expression ) : m_expression( expression ) {} diff --git a/src/FitResult.cpp b/src/FitResult.cpp index dfd54c36dc0..309a2213e57 100644 --- a/src/FitResult.cpp +++ b/src/FitResult.cpp @@ -48,8 +48,6 @@ bool FitResult::readFile( const std::string& fname ) return false; } CHECK.close(); - - // auto lines = vectorFromFile( fname ); std::vector parameterLines; processFile( fname, [this, ¶meterLines]( auto& line ) { @@ -105,12 +103,12 @@ void FitResult::writeToFile( const std::string& fname ) std::ofstream outlog; outlog.open( fname ); - for ( int i = 0; i < m_covarianceMatrix.GetNrows(); ++i ) { - auto param = m_mps->getParPtr( i ); + for (size_t i = 0; i < (size_t)m_covarianceMatrix.GetNrows(); ++i ) { + auto param = m_mps->at(i); outlog << "Parameter" << " " << param->name() << " " << param->iFixInit() << " " << param->mean() << " " - << m_mps->getParPtr( i )->err() << " "; - for ( int j = 0; j < m_covarianceMatrix.GetNcols(); ++j ) outlog << m_covarianceMatrix[i][j] << " "; + << m_mps->at(i)->err() << " "; + for (size_t j = 0; j < (size_t)m_covarianceMatrix.GetNcols(); ++j ) outlog << m_covarianceMatrix[i][j] << " "; outlog << std::endl; } outlog << std::setprecision( 8 ); @@ -134,9 +132,9 @@ FitResult::FitResult( const Minimiser& mini ) m_covarianceMatrix = M; m_status = mini.status(); m_nParam = 0; - for ( unsigned int i = 0; i < m_mps->size(); ++i ) { - if ( m_mps->getParPtr( i )->iFixInit() == 0 ) m_nParam++; - m_covMapping[ m_mps->getParPtr(i)->name() ] = i; + for (size_t i = 0; i < m_mps->size(); ++i ) { + if ( m_mps->at(i)->iFixInit() == 0 ) m_nParam++; + m_covMapping[ m_mps->at(i)->name() ] = i; } } @@ -148,8 +146,8 @@ FitResult::FitResult( const MinuitParameterSet& mps, const TMatrixD& covMini ) : } m_covarianceMatrix.ResizeTo( covMini.GetNcols(), covMini.GetNrows() ); m_covarianceMatrix = covMini; - for ( unsigned int i = 0; i < m_mps->size(); ++i ) { - if ( m_mps->getParPtr( i )->iFixInit() == 0 ) m_nParam++; + for (size_t i = 0; i < m_mps->size(); ++i ) { + if ( m_mps->at(i)->iFixInit() == 0 ) m_nParam++; } } @@ -203,8 +201,8 @@ std::vector FitResult::getFloating( const bool& extended ) con TMatrixD FitResult::getReducedCovariance( const bool& extended ) const { std::vector floating_indices; - for ( unsigned int i = 0; i < m_mps->size(); ++i ) { - auto param = m_mps->getParPtr( i ); + for (size_t i = 0; i < m_mps->size(); ++i ) { + auto param = m_mps->at(i); if ( ( param->iFixInit() == 0 || extended ) && param->err() > 1e-6 ) floating_indices.push_back( i ); } TMatrixD reducedCov( floating_indices.size(), floating_indices.size() ); diff --git a/src/Lineshapes.cpp b/src/Lineshapes.cpp index 4215758bbb9..c61060562a7 100644 --- a/src/Lineshapes.cpp +++ b/src/Lineshapes.cpp @@ -103,9 +103,9 @@ bool Lineshape::Factory::isLineshape( const std::string& lineshape ) size_t pos = lineshape.find( "." ); if ( pos == std::string::npos ) - return AmpGen::Factory::get(lineshape, true) != nullptr; + return AmpGen::Factory::get(lineshape, true) != nullptr; else - return AmpGen::Factory::get(lineshape.substr(0, pos), true ) != nullptr; + return AmpGen::Factory::get(lineshape.substr(0, pos), true ) != nullptr; } Expression Lineshape::Factory::get( const std::string& lineshape, const Expression& s, const Expression& s1, @@ -115,11 +115,11 @@ Expression Lineshape::Factory::get( const std::string& lineshape, const Expressi size_t pos = lineshape.find( "." ); if ( pos == std::string::npos ) { - auto it = AmpGen::Factory::get( lineshape ); + auto it = AmpGen::Factory::get( lineshape ); if ( !it ) ERROR( "Lineshape : " << lineshape << " not found" ); return it->get( s, s1, s2, particleName, L, "", dbexpressions ); } else { - return AmpGen::Factory::get(lineshape.substr(0, pos))->get( s, s1, s2, particleName, L, lineshape.substr( pos + 1 ), dbexpressions ); + return AmpGen::Factory::get(lineshape.substr(0, pos))->get( s, s1, s2, particleName, L, lineshape.substr( pos + 1 ), dbexpressions ); } } @@ -130,11 +130,11 @@ Expression Lineshape::Factory::get(const std::string& lineshape, const Expressio size_t pos = lineshape.find( "." ); if ( pos == std::string::npos ) { - auto it = AmpGen::Factory::get( lineshape ); + auto it = AmpGen::Factory::get( lineshape ); if ( !it ) ERROR( "Lineshape : " << lineshape << " not found" ); return it->get(s, p, particleName, L, "", dbexpressions ); } else { - return AmpGen::Factory::get( lineshape.substr( 0, pos ) )->get(s, p, particleName, L, lineshape.substr( pos + 1 ), dbexpressions ); + return AmpGen::Factory::get( lineshape.substr( 0, pos ) )->get(s, p, particleName, L, lineshape.substr( pos + 1 ), dbexpressions ); } } diff --git a/src/Lineshapes/Flatte.cpp b/src/Lineshapes/Flatte.cpp index 220cdfc1f47..06827969cbf 100644 --- a/src/Lineshapes/Flatte.cpp +++ b/src/Lineshapes/Flatte.cpp @@ -10,12 +10,12 @@ using namespace std::complex_literals; Expression aSqrtTerm( const Expression& s, const Expression& m0 ) { Expression a2 = 1.0 - ( 4 * m0 * m0 ) / s; - return Ternary( a2 > Constant( 0 ), sqrt( a2 ), Constant( 0 ) ); + return Ternary( a2 > 0., sqrt( a2 ), Constant( 0 ) ); } Expression fSqrtTerm( const Expression& s, const Expression& m0 ) { - return complex_sqrt( 1.0 - ( 4 * m0 * m0 ) / s ); + return complex_sqrt( 1.0 - 4*m0*m0/ s ); } DEFINE_LINESHAPE( Flatte ) { diff --git a/src/Minimiser.cpp b/src/Minimiser.cpp index bd92ccfbc44..051e6ca676d 100644 --- a/src/Minimiser.cpp +++ b/src/Minimiser.cpp @@ -32,8 +32,8 @@ void Minimiser::print( const double& LL ) double Minimiser::operator()( const double* xx ) { - for ( unsigned int i = 0; i < m_mapping.size(); ++i ) { - m_parSet->getParPtr( m_mapping[i] )->setCurrentFitVal( xx[i] ); + for(size_t i = 0; i < m_mapping.size(); ++i ) { + m_parSet->at( m_mapping[i] )->setCurrentFitVal( xx[i] ); } double LL = m_theFunction(); for ( auto& extendTerm : m_extendedTerms ) { @@ -44,8 +44,8 @@ double Minimiser::operator()( const double* xx ) void Minimiser::GradientTest() { - for ( unsigned int i = 0; i < m_mapping.size(); ++i ) { - auto parameter = m_parSet->getParPtr( m_mapping[i] ); + for (size_t i = 0; i < m_mapping.size(); ++i) { + auto parameter = m_parSet->at( m_mapping[i] ); double m = parameter->mean(); parameter->setCurrentFitVal( parameter->meanInit() + parameter->stepInit() ); double vp = FCN(); @@ -78,7 +78,7 @@ void Minimiser::prepare() m_covMatrix.clear(); for(size_t i = 0 ; i < m_parSet->size(); ++i) { - auto par = m_parSet->getParPtr(i); + auto par = m_parSet->at(i); if ( par->iFixInit() != 0 ) continue; m_minimiser->SetVariable(m_mapping.size(), par->name(), par->mean(), par->stepInit()); if ( par->minInit() != 0 || par->maxInit() != 0 ) @@ -100,8 +100,8 @@ bool Minimiser::doFit() { m_lastPrint = 999; ROOT::Math::Functor f( *this, m_nParams ); - for ( unsigned int i = 0; i < m_mapping.size(); ++i ) { - MinuitParameter* par = m_parSet->getParPtr( m_mapping[i] ); + for (size_t i = 0; i < m_mapping.size(); ++i ) { + MinuitParameter* par = m_parSet->at( m_mapping[i] ); m_minimiser->SetVariable( i, par->name(), par->mean(), par->stepInit() ); if ( par->minInit() != 0 || par->maxInit() != 0 ) m_minimiser->SetVariableLimits( i, par->minInit(), par->maxInit() ); @@ -109,8 +109,8 @@ bool Minimiser::doFit() m_minimiser->SetFunction( f ); m_minimiser->Minimize(); - for ( unsigned int i = 0; i < m_nParams; ++i ) { - auto par = m_parSet->getParPtr( m_mapping[i] ); + for (size_t i = 0; i < m_nParams; ++i ) { + auto par = m_parSet->at( m_mapping[i] ); double error = *( m_minimiser->Errors() + i ); par->setResult( *( m_minimiser->X() + i ), error, error, error ); for ( unsigned int j = 0; j < m_nParams; ++j ) { diff --git a/src/MinuitParameterSet.cpp b/src/MinuitParameterSet.cpp index 72b23ba6b77..8c1f7ea8cc1 100644 --- a/src/MinuitParameterSet.cpp +++ b/src/MinuitParameterSet.cpp @@ -22,7 +22,7 @@ using namespace AmpGen; MinuitParameterSet::MinuitParameterSet() = default; MinuitParameterSet::MinuitParameterSet( const MinuitParameterSet& other ) - : _parPtrList( other._parPtrList ), _keyAccess( other._keyAccess ) + : m_parameters( other.m_parameters ), m_keyAccess( other.m_keyAccess ) { } @@ -40,97 +40,98 @@ bool MinuitParameterSet::addToEnd( MinuitParameter* parPtr ) bool success = true; if ( nullptr == parPtr ) return false; - _parPtrList.push_back( parPtr ); + m_parameters.push_back( parPtr ); - if ( _keyAccess.find( parPtr->name() ) != _keyAccess.end() ) { + if ( m_keyAccess.find( parPtr->name() ) != m_keyAccess.end() ) { WARNING( "Parameter with name " << parPtr->name() << " already exists!" ); } - _keyAccess[parPtr->name()] = parPtr; + m_keyAccess[parPtr->name()] = parPtr; return success; } MinuitParameter* MinuitParameterSet::add( const std::string& name, const unsigned int& flag, const double& mean, - const double& sigma, const double& min, const double& max ) + const double& sigma, const double& min, const double& max ) { addToEnd( new MinuitParameter( name, MinuitParameter::Flag(flag), mean, sigma, min, max ) ); - return _keyAccess[name]; + return m_keyAccess[name]; } bool MinuitParameterSet::add( MinuitParameter* parPtr ) { return addToEnd( parPtr ); } bool MinuitParameterSet::unregister( MinuitParameter* parPtr ) { - if ( _parPtrList.end() == std::find( _parPtrList.begin(), _parPtrList.end(), parPtr ) ) { + if ( m_parameters.end() == std::find( m_parameters.begin(), m_parameters.end(), parPtr ) ) { WARNING( "parPtr you want to unregister is not part of this list!" ); return false; } - _parPtrList.erase( remove( _parPtrList.begin(), _parPtrList.end(), parPtr ), _parPtrList.end() ); + m_parameters.erase( remove( m_parameters.begin(), m_parameters.end(), parPtr ), m_parameters.end() ); return true; } -unsigned int MinuitParameterSet::size() const { return _parPtrList.size(); } - -MinuitParameter* MinuitParameterSet::getParPtr( unsigned int i ) const -{ - if ( i >= _parPtrList.size() ) return nullptr; - return _parPtrList[i]; -} +unsigned int MinuitParameterSet::size() const { return m_parameters.size(); } void MinuitParameterSet::deleteListAndObjects() { - for ( auto it = _parPtrList.begin(); it != _parPtrList.end(); ++it ) { - delete *it; - } - _parPtrList.clear(); + for ( auto it = m_parameters.begin(); it != m_parameters.end(); ++it ) delete *it; + m_parameters.clear(); } -void MinuitParameterSet::deleteListKeepObjects() { _parPtrList.clear(); } +void MinuitParameterSet::deleteListKeepObjects() { m_parameters.clear(); } void MinuitParameterSet::print( std::ostream& os ) const { - for ( unsigned int i = 0; i < size(); i++ ) { - if ( nullptr == getParPtr( i ) ) continue; + for (size_t i = 0; i < size(); i++ ) { os << '\n'; - getParPtr( i )->print( os ); + m_parameters[i]->print(os); } os << '\n'; } void MinuitParameterSet::printVariable( std::ostream& os ) const { - for ( unsigned int i = 0; i < size(); i++ ) { - if ( nullptr == getParPtr( i ) ) continue; - if ( getParPtr( i )->iFixInit() == 1 ) continue; /// hide parameter + for (size_t i = 0; i < size(); i++ ) { + if ( m_parameters[i]->iFixInit() == 1 ) continue; /// hide parameter os << '\n'; - getParPtr( i )->print( os ); + m_parameters[i]->print( os ); } } MinuitParameter* MinuitParameterSet::operator[]( const std::string& key ) { - auto it = _keyAccess.find( key ); - if ( it == _keyAccess.end() ) { + auto it = m_keyAccess.find( key ); + if ( it == m_keyAccess.end() ) { WARNING( "Parameter: " << key << " not found" ); } return it->second; } + MinuitParameter* MinuitParameterSet::operator[]( const std::string& key ) const { - auto it = _keyAccess.find( key ); - if ( it == _keyAccess.end() ) { + auto it = m_keyAccess.find( key ); + if ( it == m_keyAccess.end() ) { WARNING( "Parameter: " << key << " not found" ); } return it->second; } -MinuitParameter* MinuitParameterSet::operator[]( const unsigned int& key ) { return _parPtrList[key]; } + +MinuitParameter* MinuitParameterSet::operator[]( const size_t& key ) { return m_parameters[key]; } + MinuitParameter* MinuitParameterSet::at( const std::string& key ) { - if ( _keyAccess.count( key ) == 0 ) { + if ( m_keyAccess.count( key ) == 0 ) { ERROR( key << " not found" ); return nullptr; } else - return _keyAccess[key]; + return m_keyAccess[key]; } +MinuitParameter* MinuitParameterSet::at( const size_t& index ) const +{ + if( index >= m_parameters.size() ) + ERROR( "Attempting to access parameter " << index << " when only " << m_parameters.size() << " have been defined" ); + return index < m_parameters.size() ? m_parameters[index] : nullptr; +} + + void MinuitParameterSet::tryParameter( const std::vector& line ) { if ( line.size() == 4 || line.size() == 6 ) { @@ -145,7 +146,7 @@ void MinuitParameterSet::tryParameter( const std::vector& line ) if ( status ) { if ( OptionsParser::printHelp() ) INFO( "MINUIT: Registered " << line[0] << " (flag " << flag << ") = " << mean << ", step=" << step << " (" - << min << "," << max << ")" ); + << min << "," << max << ")" ); add( new MinuitParameter( line[0], MinuitParameter::Flag(flag), mean, step, min, max ) ); } return; @@ -165,20 +166,11 @@ void MinuitParameterSet::tryParameter( const std::vector& line ) double min_im = 0; double max_im = 0; if ( !status ) return; - - if ( NamedParameter( "MinuitParameterSet::RegulateParameters", 0 ) == 1 ) { - if ( mean_re < 0 ) { - mean_re = -mean_re; - mean_im = mean_im + M_PI; - } - mean_im = atan2( sin( mean_im ), cos( mean_im ) ); - max_re = 1000; - } if ( OptionsParser::printHelp() ) { INFO( "MINUIT: Complex " << line[0] << "_Re (flag " << flag_re << ") = " << mean_re << ", step=" << step_re - << " (" << min_re << "," << max_re << ")" ); + << " (" << min_re << "," << max_re << ")" ); INFO( "MINUIT: Complex " << line[0] << "_Im (flag " << flag_im << ") = " << mean_im << ", step=" << step_im - << " (" << min_im << "," << max_im << ")" ); + << " (" << min_im << "," << max_im << ")" ); } add( new MinuitParameter( line[0] + "_Re", MinuitParameter::Flag(flag_re), mean_re, step_re, min_re, max_re ) ); add( new MinuitParameter( line[0] + "_Im", MinuitParameter::Flag(flag_im), mean_im, step_im, min_im, max_im ) ); @@ -197,7 +189,6 @@ void MinuitParameterSet::tryParameter( const std::vector& line ) double min_im = lexical_cast( line[9], status ); double max_im = lexical_cast( line[10], status ); if ( !status ) return; - add( new MinuitParameter( line[0] + "_Re", MinuitParameter::Flag(flag_re), mean_re, step_re, min_re, max_re ) ); add( new MinuitParameter( line[0] + "_Im", MinuitParameter::Flag(flag_im), mean_im, step_im, min_im, max_im ) ); } @@ -210,8 +201,8 @@ void MinuitParameterSet::tryAlias( const std::vector& line ) std::string name = line[0]; MinuitExpression* expr = new MinuitExpression( line, this ); if ( expr->isGood() ) { - _aliasList.push_back( expr ); - _keyAccess[name] = expr; + m_expressions.push_back( expr ); + m_keyAccess[name] = expr; } else { ERROR( "Expression is ill-formed: " << line[0] ); delete expr; @@ -222,23 +213,20 @@ void MinuitParameterSet::tryAlias( const std::vector& line ) void MinuitParameterSet::loadFromStream() { auto ppfl = OptionsParser::getMe(); - std::vector> protoAliases; - for ( auto it = ppfl->begin(); it != ppfl->end(); ++it ) { tryParameter( it->second ); if ( it->second.size() >= 3 && it->second[1] == "=" ) protoAliases.push_back( it->second ); } for ( auto& alias : protoAliases ) tryAlias( alias ); - // print(); } void MinuitParameterSet::loadFromFile( const std::string& file ) { processFile( file, [this]( auto& line ) { - this->tryParameter( split( line, {' ', '\t'} ) ); - this->tryAlias( split( line, {' ', '\t'} ) ); - } ); + this->tryParameter( split( line, {' ', '\t'} ) ); + this->tryAlias( split( line, {' ', '\t'} ) ); + } ); } MinuitParameterSet::~MinuitParameterSet() = default; @@ -257,8 +245,30 @@ void MinuitParameterSet::resetToInit() } MinuitParameter* MinuitParameterSet::addOrGet( const std::string& name, const unsigned int& flag, const double& mean, - const double& sigma, const double& min, const double& max ) + const double& sigma, const double& min, const double& max ) { - if ( _keyAccess.count( name ) != 0 ) return _keyAccess[name]; + if ( m_keyAccess.count( name ) != 0 ) return m_keyAccess[name]; return add( name, flag, mean, sigma, min, max ); } +std::map& MinuitParameterSet::map() { return m_keyAccess; } +const std::map& MinuitParameterSet::const_map() const { return m_keyAccess; } +MinuitParameterSet::const_iterator MinuitParameterSet::cbegin() const { return m_parameters.cbegin(); } +MinuitParameterSet::const_iterator MinuitParameterSet::cend() const { return m_parameters.cend(); } +MinuitParameterSet::iterator MinuitParameterSet::begin() { return m_parameters.begin(); } +MinuitParameterSet::iterator MinuitParameterSet::end() { return m_parameters.end(); } +MinuitParameterSet::const_iterator MinuitParameterSet::begin() const { return m_parameters.cbegin(); } +MinuitParameterSet::const_iterator MinuitParameterSet::end() const { return m_parameters.cend(); } + +MinuitParameter* MinuitParameterSet::find( const std::string& key ) const +{ + auto it = m_keyAccess.find(key); + return it == m_keyAccess.end() ? nullptr : it->second; +} + +double MinuitParameterSet::operator()( const std::string& name ) +{ + if ( m_keyAccess.find(name) == m_keyAccess.end() ) { + ERROR( "Cannot find parameter " << name ); + } + return m_keyAccess[name]->mean(); +} diff --git a/src/Pade.cpp b/src/Pade.cpp new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/PhaseSpace.cpp b/src/PhaseSpace.cpp index 615767d8169..6caf2832251 100644 --- a/src/PhaseSpace.cpp +++ b/src/PhaseSpace.cpp @@ -59,14 +59,14 @@ Event PhaseSpace::makeEvent(const size_t& cacheSize) rt.set(0, { 0, pd[0], 0, sqrt( pd[0] * pd[0] + m_mass[0] * m_mass[0] )} ); - for( unsigned int i = 1 ; i != m_nt ; ++i ){ + for(size_t i = 1 ; i != m_nt ; ++i ){ rt.set( i, { 0, -pd[i-1], 0, sqrt( pd[i-1] * pd[i-1] + m_mass[i] * m_mass[i] ) } ); double cZ = 2 * rndm() - 1; double sZ = sqrt( 1 - cZ * cZ ); double angY = 2 * M_PI * rndm(); double cY = cos(angY); double sY = sin(angY); - for ( unsigned int j = 0; j <= i; j++ ) { + for (size_t j = 0; j <= i; j++ ) { double x = rt[4*j+0]; double y = rt[4*j+1]; double z = rt[4*j+2]; @@ -79,7 +79,7 @@ Event PhaseSpace::makeEvent(const size_t& cacheSize) if ( i == ( m_nt - 1 ) ) break; double beta = pd[i] / sqrt( pd[i] * pd[i] + invMas[i] * invMas[i] ); double gamma = 1./sqrt( 1 - beta*beta); - for ( unsigned int j = 0; j <= i; j++ ){ + for (size_t j = 0; j <= i; j++ ){ double E = rt[4*j+3]; double py = rt[4*j+1]; rt[4*j+1] = gamma*( py + beta * E ); @@ -93,10 +93,9 @@ Event PhaseSpace::makeEvent(const size_t& cacheSize) bool PhaseSpace::setDecay( const double& m0, const std::vector& mass ) { - unsigned int n; m_nt = mass.size(); m_teCmTm = m0; - for ( n = 0; n < m_nt; n++ ) { + for (size_t n = 0; n < m_nt; n++) { m_mass[n] = mass[n]; m_teCmTm -= mass[n]; } @@ -104,7 +103,7 @@ bool PhaseSpace::setDecay( const double& m0, const std::vector& mass ) double emmax = m_teCmTm + m_mass[0]; double emmin = 0; double wtmax = 1; - for ( n = 1; n < m_nt; n++ ) { + for (size_t n = 1; n < m_nt; n++) { emmin += m_mass[n - 1]; emmax += m_mass[n]; wtmax *= q( emmax, emmin, m_mass[n] ); diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index e7efc8aa0a4..ad406962d9e 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -342,8 +342,6 @@ Expression PolarisedSum::probExpression(const Tensor& T_matrix, const std::vecto size_t it = T_matrix.dims()[0]; Tensor rho = Identity(it); if(it == 2) rho = rho + Sigma[0] * p[0] + Sigma[1] * p[1] + Sigma[2]*p[2]; - rho.print(); - Expression rt = rho(a,b) * TT(b,a); return Real(rt); } @@ -411,6 +409,5 @@ real_t PolarisedSum::getValNoCache( const Event& evt ) return m_probExpression( copy.getCachePtr() ); } - void PolarisedSum::setWeight( MinuitParameter* param ){ m_weightParam = param ; } double PolarisedSum::getWeight() const { return m_weightParam == nullptr ? 1.0 : m_weightParam->mean() ; } diff --git a/src/ThreeBodyCalculators.cpp b/src/ThreeBodyCalculators.cpp index d099bb7c5ef..2175a82aa8f 100644 --- a/src/ThreeBodyCalculators.cpp +++ b/src/ThreeBodyCalculators.cpp @@ -44,14 +44,9 @@ using namespace AmpGen; template double dispersive( FCN& fcn , const double& s, double min , double max ) { TF1 fcn_tf1 = TF1( "fcn_tf1",fcn, min, max, 0 ); - ROOT::Math::WrappedTF1* wf1 = new ROOT::Math::WrappedTF1( fcn_tf1 ); - ROOT::Math::GSLIntegrator ig( ROOT::Math::IntegrationOneDim::kADAPTIVE ); - ROOT::Math::IGenFunction& stupid = *( wf1->Clone() ); - ig.SetFunction( stupid ); - ig.SetRelTolerance( 0.001 ); - double rt = ig.IntegralCauchy(stupid,min,max,s); - delete wf1; - return rt; + ROOT::Math::GSLIntegrator ig(ROOT::Math::IntegrationOneDim::kADAPTIVE, 0.0001); + ig.SetFunction( ROOT::Math::WrappedTF1(fcn_tf1) ); + return ig.IntegralCauchy(min,max,s); } TGraph* ThreeBodyCalculator::runningMass( diff --git a/src/Vertex.cpp b/src/Vertex.cpp index e788a56402a..4c0dfd756b8 100644 --- a/src/Vertex.cpp +++ b/src/Vertex.cpp @@ -19,7 +19,7 @@ const Tensor::Index nu = Tensor::Index(); const Tensor::Index alpha = Tensor::Index(); const Tensor::Index beta = Tensor::Index(); -template <> Factory* Factory::gImpl = nullptr; +template <> Factory* Factory::gImpl = nullptr; bool Vertex::Factory::isVertex( const std::string& hash ) { return get( hash ) != nullptr; } @@ -54,19 +54,19 @@ const Tensor Metric4x4(){ return Tensor( {-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1}, {4, 4} ); } -Tensor AmpGen::Orbital_PWave( const Tensor& P, const Tensor& Q ) +Tensor AmpGen::Orbital_PWave(const Tensor& p, const Tensor& q) { - auto is = 1./make_cse( dot(P,P) ,true); - return Q - P * make_cse( dot( P, Q ) * is ); + auto is = 1./make_cse( dot(p,p) ,true); + return q - p * make_cse( dot(p, q) * is ); } -Tensor AmpGen::Orbital_DWave( const Tensor& P, const Tensor& Q ) +Tensor AmpGen::Orbital_DWave(const Tensor& p, const Tensor& q) { Tensor::Index mu; Tensor::Index nu; - Tensor L = Orbital_PWave( P, Q ); - Tensor f = L(mu) * L(nu) - make_cse( dot( L, L ) / 3. ) * Spin1Projector(P) ( mu, nu ); + Tensor L = Orbital_PWave(p, q); + Tensor f = L(mu) * L(nu) - make_cse( dot( L, L ) / 3. ) * Spin1Projector(p) ( mu, nu ); f.imposeSymmetry(0,1); f.st(); return f; @@ -149,9 +149,8 @@ DEFINE_VERTEX( S_VV_S1 ) { return Spin1Projector(P)(mu,nu) * V1( -mu ) * V2( -nu DEFINE_VERTEX( S_VV_D ) { - Tensor L2 = Orbital_DWave( P, Q ) / ( GeV * GeV ); - Tensor vtol = V1( mu ) * L2( -mu, -nu ) * V2( nu ); - return vtol; + Tensor L2 = Orbital_DWave(P, Q); + return V1(mu)*L2(-mu,-nu)*V2(nu); } DEFINE_VERTEX( S_VV_P ) From 306bec44ba541304bad275beac83e60345b225e1 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 2 Apr 2019 10:00:33 +0200 Subject: [PATCH 049/250] Remove explicit linking of tbb --- AmpGen/Plots.h | 1 - Standalone.cmake | 2 -- src/FitResult.cpp | 30 ++++++++---------------------- src/PolarisedSum.cpp | 6 ------ 4 files changed, 8 insertions(+), 31 deletions(-) diff --git a/AmpGen/Plots.h b/AmpGen/Plots.h index 7135c708329..15c5842d643 100644 --- a/AmpGen/Plots.h +++ b/AmpGen/Plots.h @@ -86,7 +86,6 @@ namespace AmpGen return plot; } - template std::vector bandPlot( EventList& events, const std::string& prefix, FCN& fcn, LinearErrorPropagator& linProp ) { diff --git a/Standalone.cmake b/Standalone.cmake index de7da148eab..a9f9f1fb13d 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -129,8 +129,6 @@ target_compile_options(AmpGen -Woverloaded-virtual $<$:-Ofast>) -target_link_libraries(AmpGen PUBLIC "tbb") - if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -lstdc++") else() diff --git a/src/FitResult.cpp b/src/FitResult.cpp index 309a2213e57..8d09be83938 100644 --- a/src/FitResult.cpp +++ b/src/FitResult.cpp @@ -32,8 +32,7 @@ FitResult::FitResult( const std::string& filename, const EventType& evtType ) std::string FitResult::getLastLine( std::ifstream& in ) const { std::string line; - while ( in >> std::ws && std::getline( in, line ) ) - ; + while ( in >> std::ws && std::getline( in, line ) ) ; return line; } @@ -52,25 +51,20 @@ bool FitResult::readFile( const std::string& fname ) processFile( fname, [this, ¶meterLines]( auto& line ) { const std::string name = split( line, ' ' )[0]; - if ( name == "Parameter" ) - parameterLines.push_back( line ); - else if ( name == "FitQuality" ) - this->setFitQuality( line ); - else if ( name == "FitFraction" ) - this->m_fitFractions.emplace_back( line, m_eventType ); - else if ( name == "Observable" ) - this->addToObservables( line ); + if ( name == "Parameter" ) parameterLines.push_back( line ); + else if ( name == "FitQuality" ) this->setFitQuality( line ); + else if ( name == "FitFraction" ) this->m_fitFractions.emplace_back( line, m_eventType ); + else if ( name == "Observable" ) this->addToObservables( line ); } ); - unsigned int nParameters = parameterLines.size(); - + size_t nParameters = parameterLines.size(); m_covarianceMatrix.ResizeTo( parameterLines.size(), parameterLines.size() ); m_mps = std::make_shared(); - for ( unsigned int i = 0; i < nParameters; ++i ) { + for (size_t i = 0; i < nParameters; ++i ) { auto tokens = split( parameterLines[i], ' ' ); m_covMapping[tokens[1]] = i; m_mps->add( new MinuitParameter( tokens[1], MinuitParameter::Flag(stoi( tokens[2] ) ), stod( tokens[3] ), stod( tokens[4] ), 0, 0 ) ); - for ( unsigned int j = 0; j < nParameters; ++j ) m_covarianceMatrix( i, j ) = stod( tokens[5 + j] ); + for (size_t j = 0; j < nParameters; ++j ) m_covarianceMatrix( i, j ) = stod( tokens[5 + j] ); } return true; @@ -187,14 +181,6 @@ std::vector FitResult::getFloating( const bool& extended ) con for ( auto& param : *m_mps ) { if ( ( param->iFixInit() == 0 || extended ) && param->err() > 1e-6 ) floating.push_back( param ); } - /* - if( extended ){ - DEBUG("Got extended error propagator:"); - for( auto& param : floating ){ - INFO( param->name() ); - } - } - */ return floating; } diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index ad406962d9e..974a70d0859 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -159,7 +159,6 @@ void PolarisedSum::prepare() for(size_t i = 0; i < m_matrixElements.size(); ++i){ for(size_t j = i; j < m_matrixElements.size(); ++j){ z += ((i==j) ? 1. : 2. ) * m_matrixElements[i].coupling()*std::conj(m_matrixElements[j].coupling())*norm(i,j); -// z += m_matrixElements[i].coupling()*std::conj(m_matrixElements[j].coupling())*norm(i,j); } } m_norm = std::real(z); @@ -185,11 +184,6 @@ void PolarisedSum::debug_norm() << "; exact=" << norm_slow / m_integrator.sampleNorm() << "; d = " << m_norm - norm_slow / m_integrator.sampleNorm() << "; sample=" << m_integrator.sampleNorm() ); -// for( int i = 0 ; i < m_matrixElements.size(); ++i){ -// for( int j = 0 ; j < m_matrixElements.size(); ++j){ -// INFO( "Norm(i="<get() ) && m_fcn.isLinked(); } diff --git a/AmpGen/Expression.h b/AmpGen/Expression.h index 4171a18111d..3b5e88e9e8c 100644 --- a/AmpGen/Expression.h +++ b/AmpGen/Expression.h @@ -173,10 +173,9 @@ namespace AmpGen such as cache states, but this currently requires manually specifying the argument ordering. */ class Parameter : public IExpression { public: - Parameter( const std::string& name = "", - const double& defaultValue = 0 , - const bool& resolved = false, - const unsigned int& fromArg = 0 ); + Parameter(const std::string& name = "", + const double& defaultValue = 0 , + const bool& resolved = false); std::string to_string(const ASTResolver* resolver = nullptr) const override; void resolve( ASTResolver& resolver ) override; operator Expression() const; @@ -189,7 +188,6 @@ namespace AmpGen std::string m_name; double m_defaultValue; bool m_resolved; - unsigned int m_fromArg; }; /** @ingroup ExpressionEngine class Ternary diff --git a/AmpGen/Version.h.in b/AmpGen/Version.h.in index 9adbb1f3413..d80b4640bbf 100644 --- a/AmpGen/Version.h.in +++ b/AmpGen/Version.h.in @@ -1,2 +1,3 @@ -#define AMPGEN_VERSION_MAJOR @AmpGen_VERSION_MAJOR@ -#define AMPGEN_VERSION_MINOR @AmpGen_VERSION_MINOR@ +#define AMPGEN_MAJOR_VERSION @AmpGen_VERSION_MAJOR@ +#define AMPGEN_MINOR_VERSION @AmpGen_VERSION_MINOR@ + diff --git a/Standalone.cmake b/Standalone.cmake index a9f9f1fb13d..9a47e5a5cec 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -26,7 +26,7 @@ include(CMakePrintHelpers) option(AMPGEN_DEBUG "AmpGen Debug printout") option(AMPGEN_TRACE "AmpGen Trace printout") -configure_file ("${PROJECT_SOURCE_DIR}/AmpGen/Version.h.in" "${PROJECT_SOURCE_DIR}/AmpGen/Version.h") +configure_file ("${PROJECT_SOURCE_DIR}/AmpGen/Version.h.in" "${CMAKE_BINARY_DIR}/AmpGenVersion.h") add_library(AmpGen SHARED ${AMPGEN_SRC} ${AMPGEN_HDR}) @@ -56,7 +56,7 @@ endif() message( STATUS "ROOT_INCLUDE_DIRS = ${ROOT_INCLUDE_DIRS}") target_include_directories(AmpGen PUBLIC "${CMAKE_SOURCE_DIR}") - +target_include_directories(AmpGen PUBLIC "${CMAKE_BINARY_DIR}") target_include_directories(AmpGen SYSTEM PUBLIC "${ROOT_INCLUDE_DIRS}") target_link_libraries(AmpGen PUBLIC ${ROOT_LIBRARIES} ${CMAKE_DL_LIBS}) diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 099e7808e45..1006cdee795 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -192,16 +192,16 @@ void CoherentSum::generateSourceCode(const std::string& fname, const double& nor p.pdf.compileWithParameters( stream ); if( includePythonBindings ) p.pdf.compileDetails( stream ); } - Expression event = Parameter("x0",0,true,0); - Expression pa = Parameter("double(x1)",0,true,0); + Expression event = Parameter("x0",0,true); + Expression pa = Parameter("double(x1)",0,true); Expression amplitude; for( unsigned int i = 0 ; i < size(); ++i ){ auto& p = m_matrixElements[i]; Expression this_amplitude = p.coupling() * Function( programatic_name( p.pdf.name() ) + "_wParams", {event} ); amplitude = amplitude + ( p.decayTree.finalStateParity() == 1 ? 1 : pa ) * this_amplitude; } - stream << CompiledExpression< std::complex, const double*, int>( amplitude , "AMP" ) << std::endl; - stream << CompiledExpression< double, const double*, int>(fcn::norm(amplitude) / normalisation, "FCN" ) << std::endl; + stream << CompiledExpression< std::complex, const double*, const int&>( amplitude , "AMP" ) << std::endl; + stream << CompiledExpression< double, const double*, const int&>(fcn::norm(amplitude) / normalisation, "FCN" ) << std::endl; if( includePythonBindings ){ stream << CompiledExpression< unsigned int >( m_matrixElements.size(), "matrix_elements_n" ) << std::endl; stream << CompiledExpression< double > ( normalisation, "normalization") << std::endl; diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index e6dc28c1dad..2dccb1bb01f 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -81,9 +81,9 @@ void CompiledExpressionBase::to_stream( std::ostream& stream ) const if( m_db.size() !=0 ) stream << "#include\n"; stream << "extern \"C\" const char* " << progName() << "_name() { return \"" << m_name << "\"; } \n"; bool enable_cuda = NamedParameter("UseCUDA",false); - size_t sizeOfStream = 0; + size_t sizeOfStream = 0; if( !enable_cuda ){ - stream << "#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wreturn-type-c-linkage\"\n"; +// stream << "#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wreturn-type-c-linkage\"\n"; stream << "extern \"C\" " << returnTypename() << " " << progName() << "(" << fcnSignature() << "){\n"; addDependentExpressions( stream , sizeOfStream ); stream << "return " << m_obj.to_string(m_resolver) << ";\n}\n"; @@ -96,7 +96,7 @@ void CompiledExpressionBase::to_stream( std::ostream& stream ) const } if( NamedParameter("IncludePythonBindings", false) == true ){ - stream << "#pragma clang diagnostic pop\n\n"; +// stream << "#pragma clang diagnostic pop\n\n"; stream << "extern \"C\" void " << progName() << "_c" << "(double *real, double *imag, " << fcnSignature() << "){\n"; stream << " auto val = " << progName() << "(" << args() << ") ;\n"; stream << " *real = val.real();\n"; diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index ff8bc927fc0..5aae70ebe37 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -18,7 +18,7 @@ #include "AmpGen/MsgService.h" #include "AmpGen/Utilities.h" #include "AmpGen/CompiledExpressionBase.h" -#include "AmpGen/Version.h" +#include "AmpGenVersion.h" using namespace AmpGen; @@ -128,6 +128,8 @@ void CompilerWrapper::compileSource( const std::string& fname, const std::string "-rdynamic", "-fPIC"}; for( auto& flag : compile_flags ) argp.push_back( flag.c_str() ); + if( m_cxx.find("clang") != std::string::npos ) + argp.push_back( "-Wno-return-type-c-linkage"); argp.push_back( fname.c_str() ); argp.push_back( "-o"); @@ -156,7 +158,7 @@ void CompilerWrapper::preamble( std::ostream& os ) const time_t now = time(0); char* dt = ctime(&now); os << "/** Generated by " << getenv("USER") << " on " << dt ; - os << " AmpGen v" << AMPGEN_VERSION_MAJOR << "." << AMPGEN_VERSION_MINOR << '\n'; + os << " AmpGen v" << AMPGEN_MAJOR_VERSION << "." << AMPGEN_MINOR_VERSION << '\n'; #if defined(__clang__) os << " clang v" << __clang_major__ << "." << __clang_minor__ << "." << __clang_patchlevel__; #elif defined(__ICC) || defined(__INTEL_COMPILER) diff --git a/src/Expression.cpp b/src/Expression.cpp index 6ad9d69f368..b1bec427576 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -148,14 +148,6 @@ Expression AmpGen::operator/( const Expression& A, const Expression& B ) if( is( as_prod.l() ) ) return ( Constant( 1./as_prod.l()() ) * A )/ as_prod.r(); if( is( as_prod.r() ) ) return ( Constant( 1./as_prod.r()() ) * A )/ as_prod.l(); } -// else if( is(A) ) { -// auto A_divide = cast(A); -// if( is(B) ){ -// auto B_divide = cast(B); -// return Divide( A_divide.l() * B_divide.r() , ( A_divide.r() * B_divide.l() ) ); -// } -// return A_divide.l() * B / A_divide.r() ; -// } else if( is(B) ) return ( A * cast(B).r() ) / cast(B).l(); else if( is(B) ) return ( A * fcn::isqrt( cast(B).arg() ) ); return Expression( Divide( A, B ) ); @@ -166,12 +158,10 @@ Expression AmpGen::operator==( const Expression& A, const Expression& B ){ retur Expression AmpGen::operator==( const double& A, const Expression& B ){ return Constant(A) == B ; } Expression AmpGen::operator==( const Expression& A, const double& B ){ return A == Constant(B) ; } -Parameter::Parameter( const std::string& name, const double& defaultValue, const bool& resolved, - const unsigned int& fromArg ) +Parameter::Parameter( const std::string& name, const double& defaultValue, const bool& resolved) : m_name( name ) , m_defaultValue( defaultValue ) , m_resolved( resolved ) - , m_fromArg( fromArg ) { } diff --git a/src/Particle.cpp b/src/Particle.cpp index 900bfb04e52..f5b133f32f9 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -213,9 +213,9 @@ Tensor Particle::P() const if ( m_index != 999 ) { const std::string index = std::to_string( m_index ); Tensor rt( std::vector( { - Parameter( index + "_Px", 0, false, 1 ), - Parameter( index + "_Py", 0, false, 1 ), - Parameter( index + "_Pz", 0, false, 1 ), 0 } ) , {4} ); + Parameter(index + "_Px"), + Parameter(index + "_Py"), + Parameter(index + "_Pz"), 0 }) , Tensor::dim(4) ); rt[3] = make_cse( fcn::sqrt( mass()*mass() + rt[0]*rt[0] + rt[1]*rt[1] + rt[2]*rt[2] ) ); // Parameter( index + "_E" , 0, false, 1 )} ), return rt; diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 974a70d0859..43b3113a612 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -294,7 +294,7 @@ void PolarisedSum::generateSourceCode(const std::string& fname, const double& no auto dim = m_eventType.dim(); size_t size = dim.first * dim.second; CompilerWrapper().preamble( stream ); - Expression event = Parameter("x0",0,true,0); + Expression event = Parameter("x0",0,true); std::vector expressions(size); for( auto& p : m_matrixElements ){ p.pdf.prepare(); diff --git a/src/Utilities.cpp b/src/Utilities.cpp index 8fe89b8f0a3..066d63c8d85 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -1,5 +1,5 @@ #include "AmpGen/Utilities.h" -#include "AmpGen/Version.h" +#include "AmpGenVersion.h" #include #include #include From 705a6f1aca432fd669b02d43165123ff26c55f89 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 3 Apr 2019 18:35:59 +0200 Subject: [PATCH 051/250] Fix AMPGEN_MAJOR/MINOR_VERSION and include fix for gaudi builds --- src/CompilerWrapper.cpp | 3 ++- src/Utilities.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index 5aae70ebe37..14a9957d8c8 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -33,7 +33,8 @@ CompilerWrapper::CompilerWrapper( const bool& verbose ) : INFO( "Using original compiler; set global variable CXX if another needed: " << AMPGEN_CXX ); m_cxx = AMPGEN_CXX; #else - ERROR( "No configured compiler; set global variable CXX" ); + m_cxx = getenv("AMPGEN_CXX") != nullptr ? std::string( getenv( "AMPGEN_CXX" ) ) : ""; + if( m_cxx == "" ) ERROR( "No configured compiler; set global variable CXX" ); #endif } } diff --git a/src/Utilities.cpp b/src/Utilities.cpp index 066d63c8d85..81c90ee59ab 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -271,7 +271,7 @@ void AmpGen::printSplash() std::cout << " ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝" << std::endl; std::cout << "\033[0m\n"; std::cout << bold_on << - " version " << AMPGEN_VERSION_MAJOR << "." << AMPGEN_VERSION_MINOR << std::endl; + " version " << AMPGEN_MAJOR_VERSION << "." << AMPGEN_MINOR_VERSION << std::endl; std::cout << " build: " ; #if defined(__clang__) std::cout << "clang " << __clang_major__ << "." << __clang_minor__ << "." << __clang_patchlevel__; From c4fe59bbaf6eb9ecda37d4c5f47f3bbc4e890c59 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 10 Apr 2019 22:47:24 +0200 Subject: [PATCH 052/250] Fixed problems with spin-one polarisation vectors, improved LASS instructions --- AmpGen/ASTResolver.h | 2 +- AmpGen/Array.h | 2 +- AmpGen/CompiledExpression.h | 6 +- AmpGen/Expression.h | 18 ++-- AmpGen/ExpressionParser.h | 4 +- AmpGen/Lineshapes.h | 31 ++++++- AmpGen/Spline.h | 2 +- AmpGen/Tensor.h | 5 +- AmpGen/Utilities.h | 2 +- AmpGen/Wigner.h | 7 +- apps/DataConverter.cpp | 7 +- apps/Fitter.cpp | 14 ++-- apps/Generator.cpp | 1 + options/FitterExample.opt | 55 ------------- src/ASTResolver.cpp | 36 ++++---- src/Array.cpp | 2 +- src/BinaryExpression.cpp | 2 +- src/CompiledExpressionBase.cpp | 14 +++- src/CompilerWrapper.cpp | 2 - src/EventType.cpp | 22 +++-- src/Expression.cpp | 12 +-- src/ExpressionParser.cpp | 4 +- src/Particle.cpp | 71 ++++++++-------- src/PolarisedSum.cpp | 5 +- src/Spline.cpp | 2 +- src/Tensor.cpp | 2 +- src/Transform.cpp | 1 - src/UnaryExpression.cpp | 2 +- src/Wigner.cpp | 145 ++++++++++++++------------------- 29 files changed, 225 insertions(+), 253 deletions(-) diff --git a/AmpGen/ASTResolver.h b/AmpGen/ASTResolver.h index 9513347ac84..a12e3878466 100644 --- a/AmpGen/ASTResolver.h +++ b/AmpGen/ASTResolver.h @@ -29,7 +29,7 @@ namespace AmpGen { bool hasSubExpressions() const; void reduceSubTrees(); void cleanup(); - void getOrderedSubExpressions( Expression& expression, std::vector>& dependentSubexpressions ); + std::vector> getOrderedSubExpressions( const Expression& expression); template void resolve( const TYPE& obj ){} template size_t addCacheFunction( const std::string& name, const ARGS&... args ) diff --git a/AmpGen/Array.h b/AmpGen/Array.h index 3074ea524cf..f53d5ea39ab 100644 --- a/AmpGen/Array.h +++ b/AmpGen/Array.h @@ -26,7 +26,7 @@ namespace AmpGen public: Array( const Expression& top, const size_t& size, const Expression& address = 0 ); std::string to_string(const ASTResolver* resolver=nullptr) const override ; - void resolve( ASTResolver& resolver ) override; + void resolve( ASTResolver& resolver ) const override; operator Expression(); complex_t operator()() const override; Expression operator[]( const Expression& address ) const; diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index 05519e197b6..16561600289 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -154,10 +154,10 @@ namespace AmpGen void debug( const double* event ) const { if ( !m_fcn.isLinked() ) { - ERROR( "Function " << name() << " not linked" ); + FATAL( "Function " << name() << " not linked" ); } if ( !m_fdb.isLinked() ) { - ERROR( "Function" << name() << " debugging symbols not linked" ); + FATAL( "Function" << name() << " debugging symbols not linked" ); } auto debug_results = m_fdb( &( m_externals[0] ), event ); for( auto& debug_result : debug_results ){ @@ -174,7 +174,7 @@ namespace AmpGen const std::string symbol = progName() ; if ( m_fcn.set( handle, symbol ) == 0 ) { ERROR( dlerror() ); - ERROR( name() << " (symbol = " << symbol << ") linking fails" ); + FATAL( name() << " (symbol = " << symbol << ") linking fails" ); return false; } if ( m_db.size() ==0 ) return true; diff --git a/AmpGen/Expression.h b/AmpGen/Expression.h index 3b5e88e9e8c..b9856d6d100 100644 --- a/AmpGen/Expression.h +++ b/AmpGen/Expression.h @@ -114,7 +114,7 @@ namespace AmpGen /// Resolve the dependencies of a tree using an ASTResolver, /// which keeps track of parameters, dependent sub-trees, etc. /// \param resolver resolver object to use - virtual void resolve( ASTResolver& resolver ) = 0; + virtual void resolve( ASTResolver& resolver ) const = 0; /// virtual descructor virtual ~IExpression() = default; /// Evaluate the expression using the tree, @@ -134,7 +134,7 @@ namespace AmpGen ~Expression() = default; std::string to_string(const ASTResolver* resolver=nullptr) const; IExpression* get() const; - void resolve( ASTResolver& resolver ); + void resolve( ASTResolver& resolver ) const; Expression operator+=( const Expression& other ) const; Expression operator*=( const Expression& other ) const; Expression operator-=( const Expression& other ) const; @@ -157,7 +157,7 @@ namespace AmpGen Constant( const complex_t& value ) : m_value(value) {} std::string to_string(const ASTResolver* resolver=nullptr) const override; - void resolve( ASTResolver& resolver ) override; + void resolve( ASTResolver& resolver ) const override; operator Expression() const; complex_t operator()() const override { return m_value; } private: @@ -177,7 +177,7 @@ namespace AmpGen const double& defaultValue = 0 , const bool& resolved = false); std::string to_string(const ASTResolver* resolver = nullptr) const override; - void resolve( ASTResolver& resolver ) override; + void resolve( ASTResolver& resolver ) const override; operator Expression() const; complex_t operator()() const override { return complex_t( m_defaultValue, 0 ); } std::string name() const { return m_name; } @@ -200,7 +200,7 @@ namespace AmpGen struct Ternary : public IExpression { Ternary( const Expression& cond, const Expression& v1, const Expression& v2 ); std::string to_string(const ASTResolver* resolver = nullptr ) const override; - void resolve( ASTResolver& resolver ) override; + void resolve( ASTResolver& resolver ) const override; operator Expression() const ; complex_t operator()() const override { return std::real(m_cond()) ? m_v1() : m_v2(); } Expression m_cond; @@ -212,7 +212,7 @@ namespace AmpGen struct SubTree : public IExpression { SubTree( const Expression& other ) ; std::string to_string(const ASTResolver* resolver = nullptr ) const override ; - void resolve( ASTResolver& resolver ) override; + void resolve( ASTResolver& resolver ) const override; operator Expression() const ; complex_t operator()() const override { return m_expression(); } uint64_t key() const; @@ -224,7 +224,7 @@ namespace AmpGen struct Function : public IExpression { Function( const std::string& name, const std::vector& args ) ; std::string to_string(const ASTResolver* resolver = nullptr ) const override ; - void resolve( ASTResolver& resolver ) override; + void resolve( ASTResolver& resolver ) const override; operator Expression() const ; complex_t operator()() const override { return 0; } std::string m_name; @@ -236,7 +236,7 @@ namespace AmpGen class IBinaryExpression : public IExpression { public: IBinaryExpression( const Expression& l, const Expression& r ) : lval( l ), rval( r ){}; - void resolve( ASTResolver& resolver ) override; + void resolve( ASTResolver& resolver ) const override; complex_t operator()() const override = 0; Expression l() const { return lval ; } Expression r() const { return rval ; } @@ -288,7 +288,7 @@ namespace AmpGen class IUnaryExpression : public IExpression { public: IUnaryExpression( const Expression& other ) : m_expression( other ){}; - void resolve( ASTResolver& resolver ) override; + void resolve( ASTResolver& resolver ) const override; complex_t operator()() const override = 0; virtual Expression d() const = 0; Expression arg() const { return m_expression ;} diff --git a/AmpGen/ExpressionParser.h b/AmpGen/ExpressionParser.h index 5f18e924dc0..42c789575c0 100644 --- a/AmpGen/ExpressionParser.h +++ b/AmpGen/ExpressionParser.h @@ -20,7 +20,7 @@ namespace AmpGen public: MinuitParameterLink( MinuitParameter* param ) ; std::string to_string(const ASTResolver* resolver=nullptr) const override ; - void resolve( ASTResolver& resolver ) override ; + void resolve( ASTResolver& resolver ) const override ; complex_t operator()() const override ; operator Expression() const ; std::string name() const; @@ -33,7 +33,7 @@ namespace AmpGen ExpressionPack( const std::vector& expressions ){ m_expressions = expressions ; } ExpressionPack( const Expression& A, const Expression& B ); std::string to_string(const ASTResolver* resolver=nullptr) const override; - void resolve( ASTResolver& resolver ) override; + void resolve( ASTResolver& resolver ) const override; complex_t operator()() const override; operator Expression() const ; private: diff --git a/AmpGen/Lineshapes.h b/AmpGen/Lineshapes.h index 72c2119ef49..ecbe98d3a7c 100644 --- a/AmpGen/Lineshapes.h +++ b/AmpGen/Lineshapes.h @@ -194,9 +194,36 @@ namespace AmpGen normally associated to the @f$ K^*(1430)^{0} @f$ resonance. The total amplitude is therefore: @f[ - \mathcal{A}(s) = \frac{2 a \sqrt{s} }{ 2 + arq^2 - 2iaq} + \frac{2+arq^2 + 2iaq}{2+arq^2 - 2iaq }\mathcal{A}_{BW}(s). + \mathcal{A}(s) = \frac{2 a \sqrt{s} }{ 2 + arq^2 - 2iaq} + \frac{2+arq^2 + 2iaq}{2+arq^2 - 2iaq }\mathcal{A}_{BW}(s) = \mathcal{A}_{NR}(s) + \mathcal{A}^{\prime}_{BW}(s). + @f] + As this expression somewhat resembles the sum of a Breit-Wigner with a slowly varying nonresonant component, the two parts are sometimes split apart with an additional production amplitude placed on one or the other. + These can be accessed separately using the modifiers LASS.BW and LASS.NR, and given independent coupling constants. From the user interface: + \code{.cpp} + K*(1430)bar0[LASS.NR]{K-,pi+} 0 2.0 0.1 0 -90 0.1 + K*(1430)bar0[LASS.BW]{K-,pi+} 0 1.5 0.1 0 20 0.1 + \endcode + Corresponds to the overall lineshape: + @f[ + \mathcal{A}(s) + = \left(\texttt{K*(1430)bar0[LASS.NR]{K-,pi+}}\right) \mathcal{A}_{NR}(s) + + \left(\texttt{K*(1430)bar0[LASS.BW]{K-,pi+}}\right) \mathcal{A}^{\prime}_{BW}(s) + = 2.0 e^{-90^\mathrm{o}} \mathcal{A}_{NR}(s) + 1.5 e^{-20^\mathrm{o}} \mathcal{A}^{\prime}_{BW}(s). + @f] + An alternative way to introduce a different coupling between the two components is to fix one coupling and to introduce an additional production coupling. + In the user interface, this might for example in @f$ D^{0} \to K^{-} \pi^{+} \pi^{0} @f$ decays: + \code{.cpp} + D0{K*(1430)bar0,pi0} 0 1.3 0.0 0 15 0.1 + K*(1430)bar0[LASS.NR]{K-,pi+} 0 2.0 0.1 0 -90 0.1 + K*(1430)bar0[LASS.BW]{K-,pi+} 2 1.0 0.0 0 0 0.0 + \endcode + Then the lineshape with production couplings will be: + @f[ + \mathcal{A}(s) + = \left(\texttt{D0{K*(1430)bar0,pi0}}\right)\left( + = \left(\texttt{K*(1430)bar0[LASS.NR]{K-,pi+}}\right) \mathcal{A}_{NR}(s) + + \mathcal{A}^{\prime}_{BW}(s) \right) + = 1.3 e^{15^\mathrm{o}} \left( 2.0 e^{-90^\mathrm{o}} \mathcal{A}_{NR}(s) + \mathcal{A}^{\prime}_{BW}(s) \right). @f] - As this expression somewhat resembles the sum of a Breit-Wigner with a slowly varying nonresonant component, the two parts are sometimes split apart with an additional production amplitude placed on one or the other. These can be accessed separately using the modifiers LASS.BW and LASS.NR. Parameter | User name | Description -----------------------|--------------------------------------|------------------------------------------------------------------------ diff --git a/AmpGen/Spline.h b/AmpGen/Spline.h index bed74747e21..30f44280ddd 100644 --- a/AmpGen/Spline.h +++ b/AmpGen/Spline.h @@ -63,7 +63,7 @@ namespace AmpGen{ const double& max ); Spline( const Spline& spline, const Expression& x ); - void resolve( ASTResolver& resolver ) override ; + void resolve( ASTResolver& resolver ) const override ; std::string to_string(const ASTResolver* resolver=nullptr) const override; operator Expression() ; complex_t operator()() const override ; diff --git a/AmpGen/Tensor.h b/AmpGen/Tensor.h index f79646e9c1e..45d88b8a8e9 100644 --- a/AmpGen/Tensor.h +++ b/AmpGen/Tensor.h @@ -91,7 +91,6 @@ namespace AmpGen Tensor operator-() const; void st(const bool simplify=false); - bool rankMatches( const Tensor& other ); void imposeSymmetry( size_t indexA, size_t indexB); @@ -137,7 +136,7 @@ namespace AmpGen auto up = std::tuple(args...); for_each(up, [&rt]( auto& f ) { rt.emplace_back(f); } ); return rt; - } + } private: std::vector m_dim; std::vector m_symmetrisedCoordinates; @@ -173,7 +172,7 @@ namespace AmpGen public: TensorExpression( const Tensor& tensor ); std::string to_string(const ASTResolver* resolver) const override; - void resolve( ASTResolver& resolver ) override; + void resolve( ASTResolver& resolver ) const override; complex_t operator()() const override; operator Expression() const; diff --git a/AmpGen/Utilities.h b/AmpGen/Utilities.h index 61355707978..72208c55c0f 100644 --- a/AmpGen/Utilities.h +++ b/AmpGen/Utilities.h @@ -111,7 +111,7 @@ namespace AmpGen { auto size = std::snprintf(nullptr, 0, format.c_str(), std::forward(args)...); std::string output(size+1,'\0'); std::sprintf(&output[0],format.c_str(), std::forward(args)...); - return output; + return output.substr(0, output.size()-1); } diff --git a/AmpGen/Wigner.h b/AmpGen/Wigner.h index be44e8a08b5..18dbe8ec5d6 100644 --- a/AmpGen/Wigner.h +++ b/AmpGen/Wigner.h @@ -22,17 +22,18 @@ class Particle; const double& J, const double& M ); - /** @ingroup Vertices function helicityTransformMatrix - Generates a helicity transform tensor (matrix) that aligns tensor P (four-vector) to the +/- ve z-axis, then boosts to the rest frame. + /** @ingroup Vertices function wickTransform + Generates a wick transform sequence that aligns tensor P (four-vector) to the +/- ve z-axis, then boosts to the rest frame. The mass may be seperately specified. The parameter ve specifies whether the initial Euler rotation is to the +/- z-axis. In the case where ve =-1, a second rotation is applied about the x-axis that aligns P to the +ve z-axis. This ensures that singly and doubly primed helicity frames remain orthonormal. */ - TransformSequence helicityTransformMatrix( const Tensor& P, const Expression& M, const int& ve =1, const bool& handleZeroCase = false ); + TransformSequence wickTransform(const Tensor& P, const Expression& M, const int& ve =1, const bool& handleZeroCase = false); Expression helicityAmplitude( const Particle& particle, const TransformSequence& parentFrame, const double& Mz, DebugSymbols* db , const int sgn=1); Tensor basisSpinor(const int& polState, const int& id); + Tensor basisVector(const int& polState); struct LS { double factor; diff --git a/apps/DataConverter.cpp b/apps/DataConverter.cpp index 815e824599e..11081dc2a08 100644 --- a/apps/DataConverter.cpp +++ b/apps/DataConverter.cpp @@ -49,6 +49,7 @@ int main( int argc, char* argv[] ) std::vector particles = NamedParameter("ParticleNames" , std::vector() ).getVector(); std::vector monitorBranches = NamedParameter("Monitors" , std::vector() ).getVector(); std::vector branchFormat = NamedParameter("BranchFormat" , std::vector() ).getVector(); + std::vector friends = NamedParameter("Friends" , std::vector() ).getVector(); bool usePIDCalib = NamedParameter("usePIDCalib" , false ); bool rejectMultipleCandidates = NamedParameter("rejectMultipleCandidates", true ); std::string cuts = vectorToString( NamedParameter("Cut","").getVector() , " && "); @@ -61,6 +62,10 @@ int main( int argc, char* argv[] ) TTree* in_tree = (TTree*)f->Get( treeName.c_str() ); in_tree->SetBranchStatus( "*", 1 ); + for( auto& frie : friends ){ + auto tokens = split( frie, ':'); + in_tree->AddFriend( tokens[1].c_str(), tokens[0].c_str() ); + } INFO( "Using cut = " << cuts ); @@ -125,7 +130,7 @@ int main( int argc, char* argv[] ) } } - EventList evts( in_tree, evtType, Branches(branches), EntryList(eventsToTake), GetGenPdf(false)); + EventList evts( in_tree, evtType, Branches(branches), EntryList(eventsToTake), GetGenPdf(false), ApplySym(true) ); INFO( "Branches = ["<< vectorToString(branches, ", " ) << "]" ); diff --git a/apps/Fitter.cpp b/apps/Fitter.cpp index 3e8396388ba..1a929991817 100644 --- a/apps/Fitter.cpp +++ b/apps/Fitter.cpp @@ -135,13 +135,14 @@ FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& if ( makePlots ) { auto ep = fr->getErrorPropagator(); + const size_t NBins = NamedParameter ("nBins" , 100 , "Number of bins used for plotting."); unsigned int counter = 1; for_each( pdf.m_pdfs, [&]( auto& f ) { std::function FCN_sig = [&](const Event& evt){ return f.prob_unnormalised(evt) ; }; auto tStartIntegral2 = std::chrono::high_resolution_clock::now(); - auto mc_plot3 = mc.makeProjections( mc.eventType().defaultProjections(100), WeightFunction(f), Prefix("tMC_Category"+std::to_string(counter) ) ); + auto mc_plot3 = mc.makeProjections( mc.eventType().defaultProjections(NBins), WeightFunction(f), Prefix("tMC_Category"+std::to_string(counter) ) ); // auto mc_plot3 = bandPlot<100>( mc, "tMC_Category" + std::to_string( counter ) + "_", f, ep ); auto tEndIntegral2 = std::chrono::high_resolution_clock::now(); @@ -233,10 +234,13 @@ int main( int argc, char* argv[] ) EventList events( dataFile, !BAR ? evtType : evtType.conj() , CacheSize(defaultCacheSize), Filter(cut) ); EventList eventsMC = mcFile == "" ? EventList( evtType) : EventList( mcFile, !BAR ? evtType : evtType.conj() , CacheSize(defaultCacheSize), Filter(simCut) ) ; - auto scale_transform = [](auto& event){ for( size_t x = 0 ; x < event.size(); ++x ) event[x] /= 1000.; }; - INFO("Changing units from MeV -> GeV"); - events.transform( scale_transform ); - eventsMC.transform( scale_transform ); + + auto scale_transform = [](auto& event){ for( size_t x = 0 ; x < event.size(); ++x ) event[x] /= 1000.; }; + if( NamedParameter("Units", "GeV").getVal() == "MeV") { + INFO("Changing units from MeV -> GeV"); + events.transform( scale_transform ); + } + eventsMC.transform( scale_transform ); INFO( "Data events: " << events.size() ); INFO( "MC events : " << eventsMC.size() ); diff --git a/apps/Generator.cpp b/apps/Generator.cpp index a80592dfa41..804530fe7d0 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -107,6 +107,7 @@ int main( int argc, char** argv ) } else if ( gen_type == "PolarisedSum" ){ PolarisedSum sig( eventType, MPS ); + RecursivePhaseSpace phsp( sig.matrixElements()[0].decayTree.quasiStableTree() , eventType, &rand ); GenerateEvents( accepted, sig, phsp, nEvents, blockSize, &rand ); } diff --git a/options/FitterExample.opt b/options/FitterExample.opt index feeb9f67ece..7446b538bf3 100644 --- a/options/FitterExample.opt +++ b/options/FitterExample.opt @@ -106,58 +106,3 @@ a(1)(1260)+::Spline::Gamma::30 2 1.17885 0 a(1)(1260)+::Spline::Gamma::31 2 1.21615 0 a(1)(1260)+::Spline::Gamma::32 2 1.25246 0 a(1)(1260)+::Spline::Gamma::33 2 1.28789 0 - -#K(1)(1270)bar-_mass 0 1270 1 1000 1500 -#K(1)(1270)bar-_width 0 90 1 50 200 -# -#gLASS::F 0 1.0 1.34906e-01 -#gLASS::R 2 1.00000e+00 0 -#gLASS::a 2 0.224 3.46447e-03 -#gLASS::phiF 0 0.0 2.45733e-01 -#gLASS::phiR 0 0.0 3.14745e-02 -#gLASS::r 2 -15.01 1.49288e-01 -# -#K(1)(1270)bar-::Spline::Min 0.613246 -#K(1)(1270)bar-::Spline::Max 2.95978 -#K(1)(1270)bar-::Spline::N 40 -#K(1)(1270)bar-::Spline::Gamma::0 2 0.000162404 0 -#K(1)(1270)bar-::Spline::Gamma::1 2 0.00386694 0 -#K(1)(1270)bar-::Spline::Gamma::2 2 0.0128833 0 -#K(1)(1270)bar-::Spline::Gamma::3 2 0.0276225 0 -#K(1)(1270)bar-::Spline::Gamma::4 2 0.048283 0 -#K(1)(1270)bar-::Spline::Gamma::5 2 0.0748626 0 -#K(1)(1270)bar-::Spline::Gamma::6 2 0.107234 0 -#K(1)(1270)bar-::Spline::Gamma::7 2 0.145263 0 -#K(1)(1270)bar-::Spline::Gamma::8 2 0.188929 0 -#K(1)(1270)bar-::Spline::Gamma::9 2 0.238422 0 -#K(1)(1270)bar-::Spline::Gamma::10 2 0.294211 0 -#K(1)(1270)bar-::Spline::Gamma::11 2 0.357122 0 -#K(1)(1270)bar-::Spline::Gamma::12 2 0.428445 0 -#K(1)(1270)bar-::Spline::Gamma::13 2 0.510093 0 -#K(1)(1270)bar-::Spline::Gamma::14 2 0.604757 0 -#K(1)(1270)bar-::Spline::Gamma::15 2 0.715757 0 -#K(1)(1270)bar-::Spline::Gamma::16 2 0.845719 0 -#K(1)(1270)bar-::Spline::Gamma::17 2 0.993541 0 -#K(1)(1270)bar-::Spline::Gamma::18 2 1.15281 0 -#K(1)(1270)bar-::Spline::Gamma::19 2 1.31566 0 -#K(1)(1270)bar-::Spline::Gamma::20 2 1.47718 0 -#K(1)(1270)bar-::Spline::Gamma::21 2 1.63572 0 -#K(1)(1270)bar-::Spline::Gamma::22 2 1.79135 0 -#K(1)(1270)bar-::Spline::Gamma::23 2 1.94481 0 -#K(1)(1270)bar-::Spline::Gamma::24 2 2.09696 0 -#K(1)(1270)bar-::Spline::Gamma::25 2 2.24862 0 -#K(1)(1270)bar-::Spline::Gamma::26 2 2.40051 0 -#K(1)(1270)bar-::Spline::Gamma::27 2 2.55328 0 -#K(1)(1270)bar-::Spline::Gamma::28 2 2.70744 0 -#K(1)(1270)bar-::Spline::Gamma::29 2 2.86345 0 -#K(1)(1270)bar-::Spline::Gamma::30 2 3.02171 0 -#K(1)(1270)bar-::Spline::Gamma::31 2 3.18254 0 -#K(1)(1270)bar-::Spline::Gamma::32 2 3.34625 0 -#K(1)(1270)bar-::Spline::Gamma::33 2 3.51307 0 -#K(1)(1270)bar-::Spline::Gamma::34 2 3.68324 0 -#K(1)(1270)bar-::Spline::Gamma::35 2 3.85695 0 -#K(1)(1270)bar-::Spline::Gamma::36 2 4.03437 0 -#K(1)(1270)bar-::Spline::Gamma::37 2 4.21566 0 -#K(1)(1270)bar-::Spline::Gamma::38 2 4.40095 0 -#K(1)(1270)bar-::Spline::Gamma::39 2 4.59036 0 -# diff --git a/src/ASTResolver.cpp b/src/ASTResolver.cpp index 69a0b644e8e..c48f5d7fe0f 100644 --- a/src/ASTResolver.cpp +++ b/src/ASTResolver.cpp @@ -40,37 +40,35 @@ void ASTResolver::reduceSubTrees() tempTrees.clear(); } -void ASTResolver::getOrderedSubExpressions( - Expression& expression, - std::vector< std::pair< uint64_t,Expression>>& dependentSubexpressions ) +std::vector> ASTResolver::getOrderedSubExpressions( const Expression& expression ) { + std::vector> subexpressions; expression.resolve( *this ); - std::map< uint64_t , size_t> used_functions; - for( size_t i = 0 ; i < dependentSubexpressions.size(); ++i ) - used_functions[ dependentSubexpressions[i].first ] = i; + std::map used_functions; do { reduceSubTrees(); - for( auto& expression : subTrees ) { - expression.second.resolve( *this ); - auto stack_pos = used_functions.find( expression.first ); + bool verbose = false; + for( auto& st : subTrees ) { + st.second.resolve( *this ); + auto stack_pos = used_functions.find( st.first ); if ( stack_pos == used_functions.end() ) { - dependentSubexpressions.emplace_back( expression.first , expression.second ); - used_functions[expression.first] = dependentSubexpressions.size() - 1; + if( verbose ) INFO("Function: " << st.first << " is at the end of stack"); + subexpressions.emplace_back( st.first , st.second ); + used_functions[st.first] = subexpressions.size() - 1; continue; } - unsigned int oldPos = stack_pos->second; - auto it = dependentSubexpressions.begin() + oldPos; - if ( it == dependentSubexpressions.end() - 1 ) continue; - - std::rotate( it, it + 1, dependentSubexpressions.end() ); - + auto oldPos = stack_pos->second; + auto it = subexpressions.begin() + oldPos; + if ( it == subexpressions.end() - 1 ) continue; + std::rotate( it, it + 1, subexpressions.end() ); for ( auto uf = used_functions.begin(); uf != used_functions.end(); ++uf ) { if ( uf->second >= oldPos ) uf->second = uf->second - 1; } - used_functions[expression.first] = dependentSubexpressions.size() - 1; + used_functions[st.first] = subexpressions.size() - 1; } } while ( hasSubExpressions() ); - std::reverse( dependentSubexpressions.begin(), dependentSubexpressions.end() ); + std::reverse( subexpressions.begin(), subexpressions.end() ); + return subexpressions; } template <> void ASTResolver::resolve( const SubTree& subTree ) diff --git a/src/Array.cpp b/src/Array.cpp index c24cc378388..f4bdb97412a 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -31,7 +31,7 @@ std::string Array::to_string(const ASTResolver* resolver) const { else return head +"[ int("+offset+")]"; } -void Array::resolve( ASTResolver& resolver ) +void Array::resolve( ASTResolver& resolver ) const { m_top.resolve( resolver ); m_address.resolve( resolver ); diff --git a/src/BinaryExpression.cpp b/src/BinaryExpression.cpp index eeb1c5e2d3a..f249e3bbdd9 100644 --- a/src/BinaryExpression.cpp +++ b/src/BinaryExpression.cpp @@ -64,7 +64,7 @@ std::string Pow::to_string(const ASTResolver* resolver) const { return " std::string Fmod::to_string(const ASTResolver* resolver) const { return "fmod(" + lval.to_string(resolver) + "," + rval.to_string(resolver) +")"; } std::string ATan2::to_string( const ASTResolver* resolver) const { return "atan2("+ lval.to_string(resolver) + "," + rval.to_string(resolver) +")"; } -void IBinaryExpression::resolve( ASTResolver& resolver ) +void IBinaryExpression::resolve( ASTResolver& resolver ) const { lval.resolve( resolver ); rval.resolve( resolver ); diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index 2dccb1bb01f..5edb7ee0049 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -30,10 +30,16 @@ void CompiledExpressionBase::resolve(const MinuitParameterSet* mps) { if( m_resolver != nullptr ) delete m_resolver ; m_resolver = new ASTResolver( m_evtMap, mps ); - m_resolver->getOrderedSubExpressions( m_obj, m_dependentSubexpressions ); - for ( auto& sym : m_db ){ - sym.second.resolve( *m_resolver ); - m_resolver->getOrderedSubExpressions( sym.second, m_debugSubexpressions ); + m_dependentSubexpressions = m_resolver->getOrderedSubExpressions( m_obj ); + for ( auto& sym : m_db ){ + auto expressions_for_this = m_resolver->getOrderedSubExpressions( sym.second); + for( auto& it : expressions_for_this ){ + bool isAlreadyInStack = false; + for( auto& jt : m_debugSubexpressions ){ + if( it.first == jt.first ){ isAlreadyInStack = true; break ; } + } + if( !isAlreadyInStack ) m_debugSubexpressions.push_back( it ); + } } m_cacheTransfers.clear(); for( auto& expression : m_resolver->cacheFunctions() ) diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index 14a9957d8c8..4401b198b4d 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -103,7 +103,6 @@ bool CompilerWrapper::compile( std::vector& expressions for ( auto& include : m_includes ) output << "#include <" << include << ">\n"; for ( auto& expression : expressions ) output << *expression << std::endl; output.close(); - compileSource( cname, oname ); for( auto& expression : expressions ) expression->link( oname ); auto twall_end = std::chrono::high_resolution_clock::now(); @@ -169,6 +168,5 @@ void CompilerWrapper::preamble( std::ostream& os ) const #endif os << '\n'; os << "*/\n"; - for ( auto& include : m_includes ) os << "#include <" << include << ">\n"; } diff --git a/src/EventType.cpp b/src/EventType.cpp index 8ee8d7d9faa..79f89b6a0b3 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -153,11 +153,12 @@ std::vector EventType::defaultProjections(const size_t& nBins) const "s" + vectorToString( indices ), "s_{" + label( indices, useRootLabelling ) + "}", nBins, ( mm.first - 0.05 ) , ( mm.second + 0.05 ) , gevcccc ); - else if( defaultObservable == "mass" ) + else if( defaultObservable == "mass" ){ axes.emplace_back( [indices]( const Event& evt ) { return sqrt( evt.s( indices ) ); }, "m" + vectorToString( indices ), "m_{" + label( indices, useRootLabelling ) + "}", nBins, - sqrt( mm.first - 0.05 ) , sqrt( mm.second + 0.05 ) , gevcc ); + mm.first > 0.05 ? sqrt(mm.first - 0.05) :0 , sqrt( mm.second + 0.05 ) , gevcc ); + } } } return axes; @@ -165,12 +166,21 @@ std::vector EventType::defaultProjections(const size_t& nBins) const Projection EventType::projection(const size_t& nBins, const std::vector& indices) const { + std::string defaultObservable = NamedParameter( "EventType::Observable", "mass2"); auto mm = minmax( indices, true ); std::string gevcccc = "\\mathrm{GeV}^{2}/c^{4}"; - return Projection( [indices]( const Event& evt ) { return evt.s( indices ); }, - "s" + vectorToString(indices), - "s_{" + label(indices, false) + "}\\, \\left[" + gevcccc + "\\right]", nBins, - ( mm.first - 0.05 ) , ( mm.second + 0.05 ) , gevcccc ); + std::string gevcc = "\\mathrm{GeV}/c^{2}"; + if( defaultObservable == "mass2" ) + return Projection( [indices]( const Event& evt ) { return evt.s( indices ); }, + "s" + vectorToString( indices ), + "s_{" + label( indices ) + "}", nBins, + ( mm.first - 0.05 ) , ( mm.second + 0.05 ) , gevcccc ); + else if( defaultObservable == "mass" ){ + return Projection( [indices]( const Event& evt ) { return sqrt( evt.s( indices ) ); }, + "m" + vectorToString( indices ), + "m_{" + label( indices ) + "}", nBins, + mm.first > 0.05 ? sqrt(mm.first - 0.05) :0 , sqrt( mm.second + 0.05 ) , gevcc ); + } } bool EventType::operator==( const EventType& other ) const diff --git a/src/Expression.cpp b/src/Expression.cpp index b1bec427576..544bf5e111f 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -188,11 +188,11 @@ Expression::Expression( const double& value ) : m_expression( std::make_shared( value ) ) {} Expression::Expression() : m_expression( std::make_shared( 0. ) ) {} -void Expression::resolve( ASTResolver& resolver ) { m_expression->resolve( resolver ); } +void Expression::resolve( ASTResolver& resolver ) const { m_expression->resolve( resolver ); } -void Constant::resolve( ASTResolver& resolver ) {} +void Constant::resolve( ASTResolver& resolver ) const {} -void Parameter::resolve( ASTResolver& resolver ) +void Parameter::resolve( ASTResolver& resolver ) const { if( !m_resolved ) resolver.resolve(*this); } @@ -206,7 +206,7 @@ std::string Ternary::to_string(const ASTResolver* resolver) const return "(" + m_cond.to_string(resolver) + "?" + m_v1.to_string(resolver) + ":" + m_v2.to_string(resolver) + ")"; } -void Ternary::resolve( ASTResolver& resolver ) +void Ternary::resolve( ASTResolver& resolver ) const { m_cond.resolve( resolver ); m_v1.resolve( resolver ); @@ -229,14 +229,14 @@ std::string Function::to_string(const ASTResolver* resolver) const { for( auto& arg : m_args ) rt += arg.to_string(resolver) + ", "; return rt.substr(0,rt.size()-2) + ")"; } -void Function::resolve( ASTResolver& resolver ) {} +void Function::resolve( ASTResolver& resolver ) const {} std::string SubTree::to_string(const ASTResolver* /*resolver*/) const { return "v"+ std::to_string(key()); } -void SubTree::resolve( ASTResolver& resolver ) +void SubTree::resolve( ASTResolver& resolver ) const { resolver.resolve( *this ); m_expression.resolve( resolver ); diff --git a/src/ExpressionParser.cpp b/src/ExpressionParser.cpp index 172281e7251..5e7850f7bdb 100644 --- a/src/ExpressionParser.cpp +++ b/src/ExpressionParser.cpp @@ -134,7 +134,7 @@ std::string MinuitParameterLink::name() const { return m_parameter->name(); } -void MinuitParameterLink::resolve( ASTResolver& resolver ) +void MinuitParameterLink::resolve( ASTResolver& resolver ) const { resolver.resolve(*this); } @@ -165,7 +165,7 @@ std::string ExpressionPack::to_string(const ASTResolver* resolver) const return rt.substr( 0, rt.length() - 2 ); } -void ExpressionPack::resolve( ASTResolver& resolver ) +void ExpressionPack::resolve( ASTResolver& resolver ) const { for ( auto& expr : m_expressions ) expr.resolve( resolver ); } diff --git a/src/Particle.cpp b/src/Particle.cpp index f5b133f32f9..f72291aa046 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -28,6 +28,7 @@ #include "AmpGen/Types.h" using namespace AmpGen; +using namespace std::complex_literals; Particle::Particle() { @@ -390,7 +391,8 @@ Expression Particle::getExpression( DebugSymbols* db, const unsigned int& index { FATAL("Invalid value for SpinFormalism: " << spinFormalism << ", possible values are: " << italic_on << " Covariant, Canonical." << italic_off ); } - Expression total( 0 ); + Expression total = 0; + Tensor::Index a; auto finalStateParticles = getFinalStateParticles(); auto orderings = identicalDaughterOrderings(); bool doSymmetrisation = !hasModifier("NoSym"); @@ -410,16 +412,20 @@ Expression Particle::getExpression( DebugSymbols* db, const unsigned int& index Tensor is = Bar( externalSpinTensor(m_polState) ); ADD_DEBUG_TENSOR( externalSpinTensor(m_polState), db ); ADD_DEBUG_TENSOR( st, db ); - Tensor::Index a; if( st.size() != 4 ){ ERROR("Spin tensor is the wrong rank = " << st.dimString() ); spinFactor = 1; } else { spinFactor = is(a) * st(a) ; } } + if( m_props->twoSpin() == 2 ){ + Tensor is = externalSpinTensor(m_polState).conjugate(); + ADD_DEBUG_TENSOR(is, db ); + spinFactor = dot(is,st); + } } if ( includeSpin && spinFormalism == "Canonical" ){ - spinFactor = helicityAmplitude( *this, TransformSequence(), double(polState())/2.0, db ); + spinFactor = helicityAmplitude(*this, TransformSequence(), m_props->isBoson() ? polState() : double(polState())/2.0, db); } if( db != nullptr ){ std::string finalStateString=""; @@ -479,35 +485,33 @@ Tensor Particle::externalSpinTensor(const int& polState, DebugSymbols* db ) cons if ( spin() == 0 ) return Tensor( std::vector( {1.} ), std::vector( {1} ) ); Tensor p = P(); - Expression pX = p.get(0) ; - Expression pY = p.get(1) ; - Expression pZ = p.get(2) ; - Expression pE = p.get(3) ; + Expression pX = p.get(0); + Expression pY = p.get(1); + Expression pZ = p.get(2); + Expression pE = p.get(3); Expression pP = fcn::sqrt( pX*pX + pY*pY + pZ*pZ ); - Expression m = fcn::sqrt( dot( p, p ) ); - complex_t I(0,1); - Expression z = pX + I*pY; - Expression zb = pX - I*pY; + Expression m = mass(); + Expression z = pX + 1i*pY; + Expression zb = pX - 1i*pY; auto id = props()->pdgID(); if ( m_props->twoSpin() == 2 && m_spinBasis == "Weyl" ) { - Expression N = 1 / ( m * fcn::sqrt( 2 ) ); - Expression em = pE+m; - if( polState == 0 ) return Tensor( { pX*pZ/(m*em), pY*pZ/(m*em), 1. + pZ*pZ/(m*em), pZ/m } ); - if( polState == 1 ) return -N*Tensor( { m + pX*zb/em, pY*zb/em -m*I, pZ*zb, zb } ); - if( polState == -1 ) return N*Tensor( { m + pX*z/em, pY*z/em + m*I, pZ*z, z } ); + Expression N = 1./(sqrt(2)); + Expression invPT2 = make_cse(Ternary( pX*pX + pY*pY > 1e-6, 1./(pX*pX+pY*pY), 0 )); + Expression invP = make_cse(Ternary( pP > 1e-6, 1./pP,0)); + Expression pZoverP = make_cse(Ternary( pP > 1e-6, pZ/pP, 1) ); + Expression f = (pP-pZ)*invPT2; + if(polState == 1) return N * Tensor({-pZoverP + 1i*z *pY*f*invP, -1i*pZoverP - 1i*z *pX*f*invP, z*invP , 0. }); + if(polState == -1) return N * Tensor({ pZoverP + 1i*zb*pY*f*invP, -1i*pZoverP - 1i*zb*pX*f*invP,-zb*invP , 0. }); + if(polState == 0) return Tensor({pX*pE*invP/m , pY*pE*invP/m , pZoverP*pE/m, pP/m}); } if( m_props->twoSpin() == 2 && m_spinBasis == "Dirac" ){ - Expression invPT2 = Ternary( pX*pX + pY*pY > 1e-6, 1./(pX*pX+pY*pY), 0 ); - if( m_props->mass() == 0 ){ - Expression N = 1./(pP*sqrt(2)); - if( polState == 1 ) return N * Tensor({ -pZ - pY*invPT2*(pP-pZ)*(pY-I*pX), - -I*pZ + pX*invPT2*(pP-pZ)*(pY-I*pX), - ( pX + I*pY), 0 } ); - if( polState == -1 ) return N * Tensor({ pZ + pY*invPT2*(pP-pZ)*(pY+I*pX), - I*pZ - pX*invPT2*(pP-pZ)*(pY+I*pX), - ( -pX + I*pY), 0 } ); - if( polState == 0 ) ERROR("Photon should does not have a rest frame, cannot be in m=0 state"); - } + if( name() == "gamma0" ){ + ERROR("Use the Weyl (helicity) basis for calculations involving photons, as they don't have a rest frame. This will result in ill-defined amplitudes."); + } + Expression N = make_cse(1./(m*(pE + m))); + if( polState == 1 ) return -Tensor({1.+ z *pX*N, 1i + z*pY*N, z*pZ*N , z*m })/sqrt(2); + if( polState == -1 ) return Tensor({1.+ zb*pX*N, -1i + zb*pY*N, zb*pZ*N , zb*m })/sqrt(2); + if( polState == -1 ) return Tensor({pX*pZ*N , pY*pZ*N, 1 + pZ*pZ*N, pZ/m }); } if( m_props->twoSpin() == 1 && m_spinBasis == "Weyl" ){ Expression n = fcn::sqrt( 2 * pP*(pP+pZ) ); @@ -518,10 +522,10 @@ Tensor Particle::externalSpinTensor(const int& polState, DebugSymbols* db ) cons Expression xi11 = make_cse(Ternary( aligned, 0, z/n )); Expression xi00 = make_cse(Ternary( aligned, 0, -zb/n )); Expression xi01 = make_cse(Ternary( aligned, 1, (pP+pZ)/n )); - if(id > 0 && polState == 1 ) return Tensor({ fa*xi10, fa*xi11, fb*xi10, fb*xi11 } ); - if(id > 0 && polState == -1 ) return Tensor({ fa*xi00, fa*xi01, -fb*xi00, -fb*xi01 } ); - if(id < 0 && polState == 1 ) return Tensor({ fb*xi00, fb*xi01, -fa*xi00, -fa*xi01 } ); - if(id < 0 && polState == -1 ) return Tensor({ fb*xi10, fb*xi11, -fa*xi01, -fa*xi11 } ); + if(id > 0 && polState == 1) return Tensor({ fa*xi10, fa*xi11, fb*xi10, fb*xi11 } ); + if(id > 0 && polState == -1) return Tensor({ fa*xi00, fa*xi01, -fb*xi00, -fb*xi01 } ); + if(id < 0 && polState == 1) return Tensor({ fb*xi00, fb*xi01, -fa*xi00, -fa*xi01 } ); + if(id < 0 && polState == -1) return Tensor({ fb*xi10, fb*xi11, -fa*xi01, -fa*xi11 } ); } if ( m_props->twoSpin() == 1 && m_spinBasis == "Dirac" ) { @@ -563,17 +567,14 @@ std::pair Particle::orbitalRange( const bool& conserveParity ) c const int S = m_props->twoSpin(); const int s1 = daughter( 0 )->props()->twoSpin(); const int s2 = daughter( 1 )->props()->twoSpin(); - int min = std::abs( S - s1 - s2 ); if ( std::abs( S + s1 - s2 ) < min ) min = std::abs( S + s1 - s2 ); if ( std::abs( S - s1 + s2 ) < min ) min = std::abs( S - s1 + s2 ); int max = S + s1 + s2; - min /= 2; max /= 2; DEBUG( "Range = " << min << " -> " << max << " conserving parity ? " << conserveParity << " J = " << S << " s1= " << s1 << " s2= " << s2 ); - if ( conserveParity == false ) return {min, max}; - + if ( conserveParity == false ) return {min, max}; int l = min; for ( ; l < max + 1; ++l ) if( conservesParity(l) ) break; if ( l == max + 1 ) return {999, 999}; diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 43b3113a612..9d6acd2eb0a 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -44,7 +44,6 @@ PolarisedSum::PolarisedSum( const EventType& type, std::string objCache = NamedParameter("PolarisedSum::ObjectCache","" ); m_verbosity = NamedParameter( "PolarisedSum::Verbosity" ,0 ); m_rules = AmplitudeRules(mps); - auto proto_amplitudes = m_rules.getMatchingRules( type, prefix); auto production_polarisations = polarisations( type.mother() ); std::vector> allStates; @@ -62,12 +61,12 @@ PolarisedSum::PolarisedSum( const EventType& type, DebugSymbols syms; for( auto& polState : allStates ){ set_polarisation_state( matrix_element, polState ); - thisExpression[ i++ ] = make_cse( matrix_element.first.getExpression(&syms) ); + thisExpression[i++] = make_cse( matrix_element.first.getExpression(&syms) ); } CompiledExpression< std::vector , const real_t*, const real_t* > expression( TensorExpression( thisExpression), matrix_element.first.decayDescriptor(), - type.getEventFormat(),debug ? syms : DebugSymbols() ,&mps ); + type.getEventFormat(), debug ? syms : DebugSymbols() ,&mps ); m_matrixElements.emplace_back(matrix_element.first, matrix_element.second, expression ); } for( auto& polState : allStates){ diff --git a/src/Spline.cpp b/src/Spline.cpp index f92461987b6..88d177fc789 100644 --- a/src/Spline.cpp +++ b/src/Spline.cpp @@ -154,7 +154,7 @@ void SplineTransfer::transfer( CompiledExpressionBase* destination ) } } -void Spline::resolve( ASTResolver& resolver ) +void Spline::resolve( ASTResolver& resolver ) const { resolver.resolve(*this); m_x.resolve(resolver); diff --git a/src/Tensor.cpp b/src/Tensor.cpp index b53519571b4..f54fa7d9434 100644 --- a/src/Tensor.cpp +++ b/src/Tensor.cpp @@ -658,7 +658,7 @@ TensorExpression::TensorExpression( const Tensor& tensor ) : std::string TensorExpression::to_string(const ASTResolver* resolver) const { return m_tensor.to_string(resolver); } -void TensorExpression::resolve( ASTResolver& resolver ){ +void TensorExpression::resolve( ASTResolver& resolver ) const { for( size_t i = 0 ; i < m_tensor.size(); ++i ) m_tensor[i].resolve( resolver ); } diff --git a/src/Transform.cpp b/src/Transform.cpp index c001be7ce19..4dbb48b3e33 100644 --- a/src/Transform.cpp +++ b/src/Transform.cpp @@ -112,7 +112,6 @@ Tensor TransformSequence::operator()( const Transform::Representation& repr ) co else return Identity(4); } Tensor::Index a,b,c; - Tensor rt = m_transforms[0](repr); rt.st(); for( size_t i = 1 ; i < m_transforms.size(); ++i ) diff --git a/src/UnaryExpression.cpp b/src/UnaryExpression.cpp index d2d60afa5e9..a00563c6833 100644 --- a/src/UnaryExpression.cpp +++ b/src/UnaryExpression.cpp @@ -67,4 +67,4 @@ Expression Norm::d() const { return 0;} Expression Real::d() const { return 0;} Expression Imag::d() const { return 0;} Expression LGamma::d() const { return 0;} -void IUnaryExpression::resolve( ASTResolver& resolver ) { m_expression.resolve( resolver ); } +void IUnaryExpression::resolve( ASTResolver& resolver ) const { m_expression.resolve( resolver ); } diff --git a/src/Wigner.cpp b/src/Wigner.cpp index 22dc9f5ad66..d39334b33c3 100644 --- a/src/Wigner.cpp +++ b/src/Wigner.cpp @@ -21,6 +21,7 @@ using namespace AmpGen; using namespace AmpGen::fcn; +using namespace std::complex_literals; double fact( const double& z ) { @@ -97,7 +98,7 @@ double AmpGen::CG( return sqrt(norm) * sum ; } -TransformSequence AmpGen::helicityTransformMatrix( const Tensor& P, +TransformSequence AmpGen::wickTransform( const Tensor& P, const Expression& mass, const int& ve, const bool& handleZero ) @@ -112,12 +113,13 @@ TransformSequence AmpGen::helicityTransformMatrix( const Tensor& P, Transform rot = ve == + 1 ? Transform( cos_theta, sin_phi*x - cos_phi*y, Transform::Type::Rotate) : Transform(-cos_theta, -sin_phi*x + cos_phi*y, Transform::Type::Rotate) ; -// Transform boost( P[3]/mass, (ve==+1) ? z : -z, Transform::Type::Boost ); - Transform boost( P[3]/mass, z, Transform::Type::Boost ); TransformSequence sequence; - sequence.add( rot ); + sequence.add(rot); if( ve == -1 ) sequence.add( Transform( -1, x, Transform::Type::Rotate ) ); - sequence.add( boost ) ; + if( std::real(mass()) != 0. ){ + Transform boost( P[3]/mass, z, Transform::Type::Boost ); + sequence.add(boost); + } return sequence; } @@ -130,12 +132,13 @@ Expression AmpGen::wigner_D(const Tensor& P, { Expression pz = make_cse( P[2] / sqrt( P[0]*P[0] + P[1] * P[1] + P[2]*P[2] ) ); Expression pt2 = make_cse( P[0]*P[0] + P[1]*P[1] ); - Expression px = P[0] / sqrt( pt2 ); - Expression py = P[1] / sqrt( pt2 ); + Expression px = P[0] / sqrt(pt2); + Expression py = P[1] / sqrt(pt2); - Expression I(std::complex(0,1)); auto little_d = make_cse ( wigner_d( pz, J, lA, lB ) ); if( J != 0 && db != nullptr ){ + db->emplace_back("pt2", pt2 ); + db->emplace_back("p2" , sqrt( P[0]*P[0] + P[1] * P[1] + P[2]*P[2] ) ); db->emplace_back("ϕ("+name+")", atan2( py, px ) ); db->emplace_back("θ("+name+")", pz ); db->emplace_back("d[" + std::to_string(J) +", " + @@ -143,9 +146,9 @@ Expression AmpGen::wigner_D(const Tensor& P, std::to_string(lB) +"](θ)", little_d ); db->emplace_back("D[" + std::to_string(J) +", " + std::to_string(lA) +", " + - std::to_string(lB) +"](Ω)", fpow(px+I*py,lB-lA) * little_d ); + std::to_string(lB) +"](Ω)", fpow(px+1i*py,lB-lA) * little_d ); } - return fpow( px + I * py, lB - lA ) * little_d; + return fpow( px + 1i* py, lB - lA ) * little_d; } std::vector AmpGen::calculate_recoupling_constants( @@ -173,62 +176,38 @@ std::vector AmpGen::calculate_recoupling_constants( return rt; } -/* -Tensor AmpGen::basis_spinor(const Tensor& p, const int& polState, const int& id, DebugSymbols* db ) -{ - Expression pX = p.get(0) ; - Expression pY = p.get(1) ; - Expression pZ = p.get(2) ; - Expression pE = p.get(3) ; - Expression pP = fcn::sqrt( pX*pX + pY*pY + pZ*pZ ); - Expression m = fcn::sqrt( dot( p, p ) ); - - complex_t I(0,1); - Expression z = pX + I*pY; - Expression zb = pX - I*pY; - Expression n = fcn::sqrt( 2 * pP*(pP+pZ) ); - Expression fa = fcn::sqrt( (pE + m)/(2*m) ); - Expression fb = fcn::sqrt( (pE - m)/(2*m) ); - Expression aligned = make_cse( Abs(pP + pZ) < 10e-6 ) ; - - Expression xi10 = make_cse(Ternary( aligned, 1, (pP+pZ)/n )); - Expression xi11 = make_cse(Ternary( aligned, 0, z/n )); - - Expression xi00 = make_cse(Ternary( aligned, 0, -zb/n )); - Expression xi01 = make_cse(Ternary( aligned, 1, (pP+pZ)/n )); - - if(id > 0 && polState == 1 ) return Tensor({fa*xi10, fa*xi11, fb*xi10, fb*xi11}); - if(id > 0 && polState == -1 ) return Tensor({fa*xi00, fa*xi01, -fb*xi00, -fb*xi01}); - if(id < 0 && polState == 1 ) return Tensor({fb*xi00, fb*xi01, -fa*xi00, -fa*xi01}); - if(id < 0 && polState == -1 ) return Tensor({fb*xi10, fb*xi11, -fa*xi01, -fa*xi11}); - - ERROR("Shouldn't reach here..."); - return Tensor(); -} -*/ Tensor AmpGen::basisSpinor(const int& polState, const int& id) { if(id > 0 && polState == 1 ) return Tensor({1, 0, 0, 0}, Tensor::dim(4)); if(id > 0 && polState == -1 ) return Tensor({0, 1, 0, 0}, Tensor::dim(4)); if(id < 0 && polState == 1 ) return Tensor({0, 0, 1, 0}, Tensor::dim(4)); if(id < 0 && polState == -1 ) return Tensor({0, 0, 0, 1}, Tensor::dim(4)); - ERROR("Shouldn't reach here..."); + ERROR("Shouldn't reach here..., polState = " << polState << " id = " << id ); return Tensor(); } +Tensor AmpGen::basisVector(const int& polState) +{ + double N = 1./sqrt(2); + if( polState == 0 ) return Tensor(std::vector({0., 0.,1.,0.}), Tensor::dim(4)); + if( polState == 1 ) return -N*Tensor(std::vector({1., 1i,0.,0.}), Tensor::dim(4)); + if( polState == -1 ) return N*Tensor(std::vector({1.,-1i,0.,0.}), Tensor::dim(4)); + ERROR("Shouldn't reach here..., polState = " << polState); + return Tensor(); +} std::vector userHelicityCouplings( const std::string& key ){ std::vector couplings; auto things = NamedParameter( key, 0).getVector(); - if( things.size() % 3 != 0 ) ERROR("Wrong number of tokens"); - for( size_t i = 0 ; i < things.size(); i+=3 ){ - LS coupling; - coupling.factor = things[i+0]; - coupling.m1 = things[i+1]; - coupling.m2 = things[i+2]; - couplings.push_back(coupling); - } - return couplings; + if( things.size() % 3 != 0 ) ERROR("Wrong number of tokens"); + for( size_t i = 0 ; i < things.size(); i+=3 ){ + LS coupling; + coupling.factor = things[i+0]; + coupling.m1 = things[i+1]; + coupling.m2 = things[i+2]; + couplings.push_back(coupling); + } + return couplings; } @@ -241,57 +220,55 @@ Expression AmpGen::helicityAmplitude(const Particle& particle, if( particle.daughters().size() > 2 ) return 1; if( particle.daughters().size() == 1 ) return helicityAmplitude( *particle.daughter(0), parentFrame, Mz, db, sgn ); - Tensor::Index a,b,c; auto myFrame = parentFrame; if( particle.spin() == 0 ) myFrame.clear(); - Tensor pInParentFrame = parentFrame( particle.P() ); + Tensor pInParentFrame = parentFrame(particle.P()); pInParentFrame.st(); - if( ! particle.isHead() ){ - auto my_sequence = helicityTransformMatrix( pInParentFrame, - fcn::sqrt(particle.massSq()), - sgn, - true ); - myFrame.add( my_sequence ); - } + auto my_sequence = wickTransform(pInParentFrame, fcn::sqrt(particle.massSq()), sgn, true ); + if( ! particle.isHead() ) myFrame.add( my_sequence ); if( particle.isStable() ) { if( particle.spin() == 0 ) return Mz==0; + // polarisation spinor / vector etc. in the quantisation of the lab (i.e. along the z-axis or lab particle momentum) + auto labPol = particle.externalSpinTensor(particle.polState(), db); + ADD_DEBUG_TENSOR(labPol, db); + auto inverseMyTransform = myFrame.inverse(); if( particle.spin() == 0.5 ) { - auto tensor = particle.externalSpinTensor(particle.polState(), db); - auto helicity_tensor = basisSpinor( 2*Mz, particle.props()->pdgID() ); - auto it = myFrame.inverse(); - auto helicity_in_frame = it( helicity_tensor, Transform::Representation::Bispinor ); - auto w = Bar(helicity_in_frame)(a) * tensor(a); - ADD_DEBUG_TENSOR( helicity_tensor, db ); - ADD_DEBUG_TENSOR( helicity_in_frame ,db); - ADD_DEBUG_TENSOR( tensor ,db ); - ADD_DEBUG(w, db); - return w; + auto basisSpinor_m1 = basisSpinor( 2*Mz, particle.props()->pdgID() ); + auto labSpinor_m1 = inverseMyTransform( basisSpinor_m1, Transform::Representation::Bispinor ); + ADD_DEBUG_TENSOR(labSpinor_m1, db); + return make_cse( Bar(labSpinor_m1)(a)*labPol(a) ); + } + if( particle.spin() == 1 ) + { + auto frameVector = basisVector(Mz); + auto labVector = inverseMyTransform( frameVector, Transform::Representation::Vector ); + auto rp = dot( labVector.conjugate(), labPol ); + ADD_DEBUG_TENSOR(labVector, db); + ADD_DEBUG(rp, db ); + return rp; } } - auto particle_couplings = particle.spinOrbitCouplings(false); auto L = particle.orbital(); - auto& d0 = *particle.daughter(0); - auto& d1 = *particle.daughter(1); - + auto& d1 = *particle.daughter(0); + auto& d2 = *particle.daughter(1); double S = 999; if( particle.S() == 0 ){ for( auto& l : particle_couplings ) if( l.first == L ){ S = l.second ; break; } if( S == 999 ) ERROR("Spin orbital coupling impossible!"); } - else S = particle.S() /2.; - - auto recoupling_constants = calculate_recoupling_constants( particle.spin(), Mz, L, S, d0.spin(), d1.spin() ); + else S = particle.S()/2.; + auto recoupling_constants = calculate_recoupling_constants( particle.spin(), Mz, L, S, d1.spin(), d2.spin() ); auto mod = particle.attribute("helAmp"); if( mod != stdx::nullopt ) recoupling_constants = userHelicityCouplings( mod.value() ); if( recoupling_constants.size() == 0 ){ WARNING( particle.uniqueString() << " " << particle.spin() << " " << particle.orbitalRange(false).first << " " << particle.orbitalRange(false).second - << " transition Mz="<< Mz << " to " << d0.spin() << " x " << d0.spin() << " cannot be coupled in (LS) = " << L << ", " << S ); + << " transition Mz="<< Mz << " to " << d1.spin() << " x " << d2.spin() << " cannot be coupled in (LS) = " << L << ", " << S ); WARNING( "Possible (LS) combinations = " << vectorToString( particle_couplings, ", ", []( auto& ls ){ return "("+std::to_string(int(ls.first)) + ", " + std::to_string(ls.second) +")";} ) ); } @@ -299,9 +276,11 @@ Expression AmpGen::helicityAmplitude(const Particle& particle, for( auto& coupling : recoupling_constants ) { auto dm = coupling.m1 - coupling.m2; - auto term = wigner_D(myFrame(d0.P()), particle.spin(), Mz, dm,db, d0.name() ); - auto h1 = helicityAmplitude(d0, myFrame, coupling.m1, db, +1); - auto h2 = helicityAmplitude(d1, myFrame, coupling.m2, db, -1); + if( (d1.name() == "gamma0" && coupling.m1 == 0) || + (d2.name() == "gamma0" && coupling.m2 == 0) ) continue; + auto term = wigner_D(myFrame(d1.P()), particle.spin(), Mz, dm,db, d1.name()); + auto h1 = helicityAmplitude(d1, myFrame, coupling.m1, db, +1); + auto h2 = helicityAmplitude(d2, myFrame, coupling.m2, db, -1); if( db != nullptr ){ db->emplace_back( "coupling" , coupling.factor ); if( coupling.factor != 1 ) db->emplace_back( "C x DD'", coupling.factor * term * h1 * h2 ); From 4b0d3887171477539ac6639488a88a6eabefca64 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 10 Apr 2019 22:59:57 +0200 Subject: [PATCH 053/250] Remove NBins option that doesn't seem to play nicely with travis .. --- apps/Fitter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/Fitter.cpp b/apps/Fitter.cpp index 1a929991817..a7d0a07ec48 100644 --- a/apps/Fitter.cpp +++ b/apps/Fitter.cpp @@ -135,14 +135,14 @@ FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& if ( makePlots ) { auto ep = fr->getErrorPropagator(); - const size_t NBins = NamedParameter ("nBins" , 100 , "Number of bins used for plotting."); +// const size_t NBins = NamedParameter ("nBins" , 100 , "Number of bins used for plotting."); unsigned int counter = 1; for_each( pdf.m_pdfs, [&]( auto& f ) { std::function FCN_sig = [&](const Event& evt){ return f.prob_unnormalised(evt) ; }; auto tStartIntegral2 = std::chrono::high_resolution_clock::now(); - auto mc_plot3 = mc.makeProjections( mc.eventType().defaultProjections(NBins), WeightFunction(f), Prefix("tMC_Category"+std::to_string(counter) ) ); + auto mc_plot3 = mc.makeProjections( mc.eventType().defaultProjections(100), WeightFunction(f), Prefix("tMC_Category"+std::to_string(counter) ) ); // auto mc_plot3 = bandPlot<100>( mc, "tMC_Category" + std::to_string( counter ) + "_", f, ep ); auto tEndIntegral2 = std::chrono::high_resolution_clock::now(); From 8295397ab9a0c7248c20b5c1d853a1c60644b9ee Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 23 Apr 2019 23:22:00 +0200 Subject: [PATCH 054/250] Reduce EDM precision, various patches for c++11 compatibility mode --- AmpGen/SumPDF.h | 5 ----- AmpGen/kMatrix.h | 2 +- apps/ConvertToSourceCode.cpp | 3 +++ options/D02piKpipi.opt | 24 ++++++++++++------------ options/mass_width.csv | 6 +++--- src/CoherenceFactor.cpp | 26 -------------------------- src/CoherentSum.cpp | 27 +++++++++++++++++++++++++++ src/Lineshapes/CoupledChannel.cpp | 2 +- src/Lineshapes/kMatrix.cpp | 6 ++++-- src/Minimiser.cpp | 2 +- src/OptionsParser.cpp | 6 ------ src/Particle.cpp | 13 +++++++------ src/Plots.cpp | 3 ++- src/PolarisedSum.cpp | 2 +- 14 files changed, 62 insertions(+), 65 deletions(-) diff --git a/AmpGen/SumPDF.h b/AmpGen/SumPDF.h index 2cdcea39e62..4a6aa4c7fa3 100644 --- a/AmpGen/SumPDF.h +++ b/AmpGen/SumPDF.h @@ -31,18 +31,13 @@ namespace AmpGen double getVal() { -// ProfileClock pc; double LL = 0; for_each( m_pdfs, []( auto& f ) { f.prepare(); } ); -// pc.stop(); -// ProfileClock eval; #pragma omp parallel for reduction( +: LL ) for ( unsigned int i = 0; i < m_events->size(); ++i ) { auto prob = ((*this))(( *m_events)[i] ); LL += log(prob); } -// eval.stop(); -// std::cout << "t [prepare] = " << pc << "; t[eval] = " << eval << "ms" << std::endl; return -2 * LL; } double operator()( const Event& evt ) diff --git a/AmpGen/kMatrix.h b/AmpGen/kMatrix.h index b242b36908b..a6fb78cc29d 100644 --- a/AmpGen/kMatrix.h +++ b/AmpGen/kMatrix.h @@ -51,7 +51,7 @@ namespace AmpGen std::vector paramVector( const std::string& name, const unsigned int& nParam ); - Tensor getPropagator(const Tensor& kMatrix, const std::vector& phaseSpace); + Tensor getPropagator(const Tensor& kMatrix, const std::vector& phaseSpace, DebugSymbols* db = nullptr); } // namespace AmpGen diff --git a/apps/ConvertToSourceCode.cpp b/apps/ConvertToSourceCode.cpp index 72783952716..5329b91bb6c 100644 --- a/apps/ConvertToSourceCode.cpp +++ b/apps/ConvertToSourceCode.cpp @@ -77,6 +77,9 @@ template void generate_source(T& pdf, EventList& normEvents, const std double pMax = 0 ; pdf.setEvents( normEvents ); pdf.prepare(); + normEvents[0].print(); + normEvents[0].printCache(); + INFO( pdf.prob_unnormalised( normEvents[0] ) ); for ( auto& evt : normEvents ) { if( type == "PolarisedSum" ){ double px, py, pz; diff --git a/options/D02piKpipi.opt b/options/D02piKpipi.opt index b81c4db0536..2ef30fe904d 100644 --- a/options/D02piKpipi.opt +++ b/options/D02piKpipi.opt @@ -3,19 +3,19 @@ Import $AMPGENROOT/options/Dbar02piKpipi.opt #necessary for K1 couplings / shape parameters -D0_radius 2 3.7559 0 -D0{K*(892)0{K+,pi-},rho(770)0{pi+,pi-}} 0 0.205 0.019 0 -8.5 4.7 -D0[P]{K*(892)0{K+,pi-},rho(770)0{pi+,pi-}} 0 0.390 0.002 0 -91.4 0.4 -D0[D]{K*(892)0{K+,pi-},rho(770)0{pi+,pi-}} 2 1.000 0.000 2 0.0 0.0 -D0{rho(1450)0{pi+,pi-},K*(892)0{K+,pi-}} 0 0.541 0.042 0 -21.8 6.5 +D0_radius 2 3.7559 0 +D0{K*(892)0{K+,pi-},rho(770)0{pi+,pi-}} 2 0.205 0.019 2 -8.5 4.7 +D0[P]{K*(892)0{K+,pi-},rho(770)0{pi+,pi-}} 2 0.390 0.002 2 -91.4 0.4 +D0[D]{K*(892)0{K+,pi-},rho(770)0{pi+,pi-}} 2 1.000 0.000 2 0.0 0.0 +D0{rho(1450)0{pi+,pi-},K*(892)0{K+,pi-}} 2 0.541 0.042 2 -21.8 6.5 # There is an additional relative phase of 180 degrees here w.r.t # what is written in the paper, due to a slightly different convention # in how the K(1) couplings have been defined. -D0{K(1)(1270)+,pi-} 0 0.653 0.040 0 69.3 5.1 -D0{K(1)(1400)+{K*(892)0{K+,pi-},pi+},pi-} 0 0.560 0.037 0 29.8 4.2 -D0{KPi40,PiPi40} 2 1.000 0.000 2 0.0 0.0 -KPi40[FOCUS.Kpi]{K+,pi-} 2 1.000 0.000 2 0.0 0.0 -KPi40[FOCUS.I32]{K+,pi-} 0 0.686 0.010 0 -149.4 4.3 -PiPi40[kMatrix.pole.1]{pi+,pi-} 0 0.438 0.009 0 -132.4 6.5 -PiPi40[kMatrix.prod.0]{pi+,pi-} 0 0.050 0.001 0 74.8 7.5 +D0{K(1)(1270)+,pi-} 2 0.653 0.040 2 69.3 5.1 +D0{K(1)(1400)+{K*(892)0{K+,pi-},pi+},pi-} 2 0.560 0.037 2 29.8 4.2 +D0{KPi40,PiPi40} 2 1.000 0.000 2 0.0 0.0 +KPi40[FOCUS.Kpi]{K+,pi-} 2 1.000 0.000 2 0.0 0.0 +KPi40[FOCUS.I32]{K+,pi-} 2 0.686 0.010 2 -149.4 4.3 +PiPi40[kMatrix.pole.1]{pi+,pi-} 2 0.438 0.009 2 -132.4 6.5 +PiPi40[kMatrix.prod.0]{pi+,pi-} 2 0.050 0.001 2 74.8 7.5 diff --git a/options/mass_width.csv b/options/mass_width.csv index 6f6050db895..436b4bb6124 100644 --- a/options/mass_width.csv +++ b/options/mass_width.csv @@ -578,9 +578,9 @@ 2.342E+03 ,3.0E+01,3.0E+01,1.6E+02 ,4.0E+01,4.0E+01,0 , ,3/2 ,-, ,F, , 0,1,S,Lambda(2325) ,uds 2.3500E+03 ,2.0E+01,1.0E+01,1.5E+02 ,1.0E+02,5.0E+01,0 , ,9/2 ,+, ,F, , 0,3,D,Lambda(2350) ,uds 2.530E+03 ,2.5E+01,2.5E+01,150 ,-1 ,-1 ,0 , ,? ,?, ,F, , 0,2,S,Lambda(2585) ,uds -1.18937E+03 ,7.0E-02,7.0E-02,8.264E-12 ,2.7E-14,2.7E-14,1 , ,1/2 ,+, ,F, 3222, +,4,R,Sigma(P11) ,uus -1.192642E+03 ,2.4E-02,2.4E-02,9.0E-03 ,8.0E-04,8.0E-04,1 , ,1/2 ,+, ,F, 3212, 0,4,R,Sigma(P11) ,uds -1.197449E+03 ,3.0E-02,3.0E-02,4.480E-12 ,3.3E-14,3.3E-14,1 , ,1/2 ,+, ,F, 3112, -,4,R,Sigma(P11) ,dds +1.18937E+03 ,7.0E-02,7.0E-02,8.264E-12 ,2.7E-14,2.7E-14,1 , ,1/2 ,+, ,F, 3222, +,4,R,Sigma ,uus +1.192642E+03 ,2.4E-02,2.4E-02,9.0E-03 ,8.0E-04,8.0E-04,1 , ,1/2 ,+, ,F, 3212, 0,4,R,Sigma ,uds +1.197449E+03 ,3.0E-02,3.0E-02,4.480E-12 ,3.3E-14,3.3E-14,1 , ,1/2 ,+, ,F, 3112, -,4,R,Sigma ,dds 1.3828E+03 ,4.0E-01,4.0E-01,3.58E+01 ,8.0E-01,8.0E-01,1 , ,3/2 ,+, ,F, 3224, +,4,R,Sigma(1385) ,uus 1.38370E+03 ,1.0E+00,1.0E+00,3.6E+01 ,5.0E+00,5.0E+00,1 , ,3/2 ,+, ,F, 3214, 0,4,R,Sigma(1385) ,uds 1.3872E+03 ,5.0E-01,5.0E-01,3.94E+01 ,2.1E+00,2.1E+00,1 , ,3/2 ,+, ,F, 3114, -,4,R,Sigma(1385) ,dds diff --git a/src/CoherenceFactor.cpp b/src/CoherenceFactor.cpp index 1da28335737..1e1eb6be5c3 100644 --- a/src/CoherenceFactor.cpp +++ b/src/CoherenceFactor.cpp @@ -517,32 +517,6 @@ void CoherenceFactor::calculateNorms() id.flush(); } -std::vector CoherentSum::cacheAddresses( const EventList& evts ) const -{ - std::vector addresses; - for ( auto& mE : m_matrixElements ) { - addresses.push_back( evts.getCacheIndex( mE.pdf ) ); - } - return addresses; -} - -complex_t CoherentSum::getVal( const Event& evt ) const -{ - complex_t value( 0., 0. ); - for ( auto& mE : m_matrixElements ) { - value += mE.coefficient * evt.getCache( mE.addressData ); - } - return value; -} - -complex_t CoherentSum::getVal( const Event& evt, const std::vector& cacheAddresses ) const -{ - complex_t value( 0., 0. ); - for ( unsigned int i = 0; i < m_matrixElements.size(); ++i ) - value += m_matrixElements[i].coefficient * evt.getCache( cacheAddresses[i] ); - return value; -} - unsigned int CoherenceFactor::getBinNumber( const Event& event ) const { int voxelID = m_voxels.getBinNumber( event ); diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 1006cdee795..ce72c724f82 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -351,3 +351,30 @@ void CoherentSum::printVal(const Event& evt) } } } + +std::vector CoherentSum::cacheAddresses( const EventList& evts ) const +{ + std::vector addresses; + for ( auto& mE : m_matrixElements ) { + addresses.push_back( evts.getCacheIndex( mE.pdf ) ); + } + return addresses; +} + +complex_t CoherentSum::getVal( const Event& evt ) const +{ + complex_t value( 0., 0. ); + for ( auto& mE : m_matrixElements ) { + value += mE.coefficient * evt.getCache( mE.addressData ); + } + return value; +} + +complex_t CoherentSum::getVal( const Event& evt, const std::vector& cacheAddresses ) const +{ + complex_t value( 0., 0. ); + for ( unsigned int i = 0; i < m_matrixElements.size(); ++i ) + value += m_matrixElements[i].coefficient * evt.getCache( cacheAddresses[i] ); + return value; +} + diff --git a/src/Lineshapes/CoupledChannel.cpp b/src/Lineshapes/CoupledChannel.cpp index 0ee3ad024e6..db183186e63 100644 --- a/src/Lineshapes/CoupledChannel.cpp +++ b/src/Lineshapes/CoupledChannel.cpp @@ -100,7 +100,7 @@ DEFINE_LINESHAPE( CoupledChannel ) ADD_DEBUG( s , dbexpressions ); for( size_t i = 0 ; i < channels.size(); i+=2 ){ Particle p( channels[i] ); - INFO( "Adding channel ... " << p.uniqueString() << " coupling = " << NamedParameter( channels[i+1] ) ); + DEBUG( "Adding channel ... " << p.uniqueString() << " coupling = " << NamedParameter( channels[i+1] ) ); Expression coupling = Parameter(channels[i+1], 0); totalWidth = totalWidth + coupling * phaseSpace(s , p, p.orbital()); totalWidthAtPole = totalWidthAtPole + coupling * phaseSpace(mass*mass, p, p.orbital()); diff --git a/src/Lineshapes/kMatrix.cpp b/src/Lineshapes/kMatrix.cpp index 073406dd3be..86db4312e06 100644 --- a/src/Lineshapes/kMatrix.cpp +++ b/src/Lineshapes/kMatrix.cpp @@ -48,7 +48,7 @@ Expression AmpGen::gFromGamma( const Expression& m, const Expression& gamma, con return fcn::sqrt( m * gamma / rho ); } -Tensor AmpGen::getPropagator(const Tensor& kMatrix, const std::vector& phaseSpace) +Tensor AmpGen::getPropagator(const Tensor& kMatrix, const std::vector& phaseSpace, DebugSymbols* db ) { unsigned int nChannels = kMatrix.dims()[0]; Tensor T( Tensor::dim(nChannels, nChannels) ); @@ -57,6 +57,7 @@ Tensor AmpGen::getPropagator(const Tensor& kMatrix, const std::vector( "Minimiser::Algorithm", "Hesse"); size_t maxCalls = NamedParameter( "Minimiser::MaxCalls" , 100000); - double tolerance = NamedParameter( "Minimiser::Tolerance" , 0.01); + double tolerance = NamedParameter( "Minimiser::Tolerance" , 0.1); m_printLevel = NamedParameter( "Minimiser::PrintLevel", 4); if ( m_minimiser != nullptr ) delete m_minimiser; m_minimiser = new Minuit2::Minuit2Minimizer(algorithm.c_str() ); diff --git a/src/OptionsParser.cpp b/src/OptionsParser.cpp index fec4a16b21d..381e51db1d1 100644 --- a/src/OptionsParser.cpp +++ b/src/OptionsParser.cpp @@ -58,12 +58,6 @@ void OptionsParser::setCommandLineArgs( int argc, char** argv ) if( key == "help" ) m_printHelp = true; m_parsedLines[key] = makeParsedStrings( key + " " + val, depth ); } - for( auto& line : m_parsedLines ) - { - std::string to_string = ""; - for( auto& thing : line.second ) to_string += thing + " "; - } - if( m_printHelp ){ std::cout << bold_on << "Usage: " << bold_off << argv[0] << italic_on << " options_file1.opt options_file2.opt --key1=value1 --key2=value2 ..." << italic_off << std::endl; std::cout << bold_on << "Options: " << bold_off << std::endl; diff --git a/src/Particle.cpp b/src/Particle.cpp index f72291aa046..5d46c7fea0c 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -515,17 +515,18 @@ Tensor Particle::externalSpinTensor(const int& polState, DebugSymbols* db ) cons } if( m_props->twoSpin() == 1 && m_spinBasis == "Weyl" ){ Expression n = fcn::sqrt( 2 * pP*(pP+pZ) ); - Expression fa = fcn::sqrt( (pE + m)/(2*m) ); - Expression fb = fcn::sqrt( (pE - m)/(2*m) ); + double isqrt_two = 1./sqrt(2); + Expression fa = fcn::sqrt(pE/m + 1); + Expression fb = fcn::sqrt(pE/m - 1); Expression aligned = make_cse( Abs(pP + pZ) < 10e-6 ) ; Expression xi10 = make_cse(Ternary( aligned, 1, (pP+pZ)/n )); Expression xi11 = make_cse(Ternary( aligned, 0, z/n )); Expression xi00 = make_cse(Ternary( aligned, 0, -zb/n )); Expression xi01 = make_cse(Ternary( aligned, 1, (pP+pZ)/n )); - if(id > 0 && polState == 1) return Tensor({ fa*xi10, fa*xi11, fb*xi10, fb*xi11 } ); - if(id > 0 && polState == -1) return Tensor({ fa*xi00, fa*xi01, -fb*xi00, -fb*xi01 } ); - if(id < 0 && polState == 1) return Tensor({ fb*xi00, fb*xi01, -fa*xi00, -fa*xi01 } ); - if(id < 0 && polState == -1) return Tensor({ fb*xi10, fb*xi11, -fa*xi01, -fa*xi11 } ); + if(id > 0 && polState == 1) return isqrt_two * Tensor({ fa*xi10, fa*xi11, fb*xi10, fb*xi11 } ); + if(id > 0 && polState == -1) return isqrt_two * Tensor({ fa*xi00, fa*xi01, -fb*xi00, -fb*xi01 } ); + if(id < 0 && polState == 1) return isqrt_two * Tensor({ fb*xi00, fb*xi01, -fa*xi00, -fa*xi01 } ); + if(id < 0 && polState == -1) return isqrt_two * Tensor({ fb*xi10, fb*xi11, -fa*xi01, -fa*xi11 } ); } if ( m_props->twoSpin() == 1 && m_spinBasis == "Dirac" ) { diff --git a/src/Plots.cpp b/src/Plots.cpp index a3903c55a2a..9e9f5685a20 100644 --- a/src/Plots.cpp +++ b/src/Plots.cpp @@ -1,4 +1,4 @@ - +#if __cplusplus >= 201402L #include "AmpGen/ErrorPropagator.h" #include "AmpGen/EventList.h" #include "AmpGen/CoherentSum.h" @@ -69,3 +69,4 @@ void AmpGen::perAmplitudePlot( const EventList& evts, dir->Write(); gFile->cd(); } +#endif diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 9d6acd2eb0a..1b91a87a9a2 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -161,7 +161,7 @@ void PolarisedSum::prepare() } } m_norm = std::real(z); - if(m_nCalls % 100 == 0 && m_prefix == "") debug_norm(); + if(m_nCalls % 10000 == 0 && m_prefix == "") debug_norm(); } tIntegral.stop(); if(m_verbosity && nChanges != 0) From d1f7e1c56ac7ab9d30ca938854a3603eb162322d Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 29 Apr 2019 10:44:58 +0200 Subject: [PATCH 055/250] Make quasistable & quasiparticle work together, add GLASS and photon propagators, additional unit tests --- AmpGen/EventType.h | 2 +- AmpGen/Lineshapes.h | 33 +++++++++++++- AmpGen/Projection.h | 9 ++-- options/MintDalitzSpecialParticles.csv | 1 + options/example_glass.opt | 17 ++++++++ options/mass_width.csv | 6 +-- src/EventType.cpp | 59 ++++++++++---------------- src/Lineshapes/GLASS.cpp | 35 +++++++++++++++ src/Lineshapes/Photon.cpp | 11 +++++ src/Minimiser.cpp | 2 +- src/Particle.cpp | 33 +++++++------- src/Projection.cpp | 2 + src/Vertex.cpp | 8 ++-- src/Wigner.cpp | 2 + test/test_Particle.cpp | 18 ++++++++ test/test_ParticleProperties.cpp | 2 +- 16 files changed, 169 insertions(+), 71 deletions(-) create mode 100644 options/example_glass.opt create mode 100644 src/Lineshapes/GLASS.cpp create mode 100644 src/Lineshapes/Photon.cpp create mode 100644 test/test_Particle.cpp diff --git a/AmpGen/EventType.h b/AmpGen/EventType.h index 21ec4cb6ec4..e9687fa950f 100644 --- a/AmpGen/EventType.h +++ b/AmpGen/EventType.h @@ -48,7 +48,7 @@ namespace AmpGen std::string label( const size_t& index, bool isRoot = true ) const; std::string label( const std::vector& index, bool isRoot = true ) const; std::vector defaultProjections(const size_t& nBins) const; - Projection projection(const size_t& nBins, const std::vector& indices) const; + Projection projection(const size_t& nBins, const std::vector& indices, const std::string& observable = "mass2") const; bool operator==( const EventType& other ) const; bool has( const std::string& name ) const; diff --git a/AmpGen/Lineshapes.h b/AmpGen/Lineshapes.h index ecbe98d3a7c..602f68bb352 100644 --- a/AmpGen/Lineshapes.h +++ b/AmpGen/Lineshapes.h @@ -230,9 +230,39 @@ namespace AmpGen @f$m@f$ | particleName_mass | Breit-Wigner mass of the resonant component, defined as energy at which the self-energy of the resonance is purely imaginary (defaults to value in PDG)
@f$\Gamma_0@f$ | particleName_width | Breit-Wigner width of the resonant component, defined as the width of resonance at the Breit-Wigner mass
@f$a@f$ | LASS::a | Scattering length of the nonresonant component, defaults to @f$2.07\mathrm{G\kern -0.1em eV}^{-1}@f$ - @f$r@f$ | LASS::r | Scattering length of the nonresonant component, defaults to @f$3.32\mathrm{G\kern -0.1em eV}^{-1}@f$ + @f$r@f$ | LASS::r | Effective interaction length of the nonresonant component, defaults to @f$3.32\mathrm{G\kern -0.1em eV}^{-1}@f$ */ DECLARE_LINESHAPE( LASS ); + /** @ingroup Lineshapes class GLASS + @brief Generalised description of the @f$ K\pi@f$ S-wave, taken from BABAR / BELLE analysis of @f$ D^{0} \to K_{S}^{0} \pi^{+} \pi^{-} @f$ https://journals.aps.org/prd/pdf/10.1103/PhysRevD.98.112012 + + Alternative parameterisation of the @f$ K \pi @f$ S-wave taken from the BABAR/BELLE analysis of @f$ D^{0} \to K_{S}^{0} \pi^{+} \pi^{-} @f$ https://journals.aps.org/prd/pdf/10.1103/PhysRevD.98.112012. + It introduces four additional parameters, two amplitudes and two phases, and is written + @f[ + \mathcal{A}(s) = R\sin\delta_R e^{i(\delta_R + 2\delta_F)} + F\sin\delta_F e^{i\delta_F} + @f] + where + @f[ + \delta_R = \phi_R + \tan^{-1}\left(\frac{m\Gamma(s)}{m^2 -s }\right) + @f] + and + @f[ + \delta_F = \phi_F + \tan^{-1}\left(\frac{2 a q}{2 + arq^2}\right), + @f] + that is, the 'resonant' and 'nonresonant' phases of the LASS formulation with additional 'proudction' phases @f$ \phi_R @f$ and @f$\phi_F @f$, and production couplings @f$R, F@f$. One of the production couplings can typically be fixed to 1, normally the resonant coupling, @f$R @f$. + + Parameter | User name | Description + -----------------------|--------------------------------------|------------------------------------------------------------------------ + @f$m@f$ | particleName_mass | Breit-Wigner mass of the resonant component, defined as energy at which the self-energy of the resonance is purely imaginary (defaults to value in PDG)
+ @f$\Gamma_0@f$ | particleName_width | Breit-Wigner width of the resonant component, defined as the width of resonance at the Breit-Wigner mass
+ @f$a@f$ | particleName::GLASS::a | Scattering length of the nonresonant component, defaults to @f$2.07\mathrm{G\kern -0.1em eV}^{-1}@f$ + @f$r@f$ | particleName::GLASS::r | Effective interaction length of the nonresonant component, defaults to @f$3.32\mathrm{G\kern -0.1em eV}^{-1}@f$ + @f$\phi_R@f$ | particleName::GLASS::phiR | Additional production phase of the resonant component, defaults to @f$0^{\mathrm{o}}@f$, measured in degrees. + @f$\phi_F@f$ | particleName::GLASS::phiF | Additional production phase of the nonresonant component, defaults to @f$0^{\mathrm{o}}@f$, measured in degrees. + @f$R@f$ | particleName::GLASS::R | Additional production coupling of the resonant component, defaults to @f$1@f$. + @f$F@f$ | particleName::GLASS::F | Additional production coupling of the nonresonant component, defaults to @f$1@f$. + */ + DECLARE_LINESHAPE(GLASS); /** @ingroup Lineshapes class Flatte @brief Lineshape to describe resonances with coupled channels such as @f$f_{0}(980)^{0} / a_{0}(980) @f$. @@ -353,6 +383,7 @@ namespace AmpGen */ DECLARE_LINESHAPE( EtaDalitz ); + DECLARE_LINESHAPE( Photon ); } // namespace Lineshape Expression Q2( const Expression& Msq, const Expression& M1sq, const Expression& M2sq ); diff --git a/AmpGen/Projection.h b/AmpGen/Projection.h index ad77e66c683..3666d1a9627 100644 --- a/AmpGen/Projection.h +++ b/AmpGen/Projection.h @@ -31,18 +31,17 @@ namespace AmpGen double m_max; double m_width; public: - const std::string name() const ; - double operator()( const Event& evt ) const ; + Projection(); template - Projection( const FCN& fcn, const std::string& name, + Projection( const FCN& fcn, const std::string& name, const std::string& xAxisTitle, const size_t& nBins, const double& min, const double& max, const std::string& units = "" ) : Projection( std::function< double( const Event& )>( fcn ), name, xAxisTitle, nBins, min, max, units ) {} Projection( const std::function& fcn, const std::string& name, const std::string& xAxisTitle, const size_t& nBins, const double& min, const double& max, const std::string& units = "" ); - TH1D* plot(const std::string& prefix="") const; - + const std::string name() const ; + double operator()( const Event& evt ) const ; std::function binFunctor() const; void setRange( const double& min, const double& max ){ m_min = (min); m_max = (max) ; } }; diff --git a/options/MintDalitzSpecialParticles.csv b/options/MintDalitzSpecialParticles.csv index 5d07dfbf05b..dc6c5866d3d 100644 --- a/options/MintDalitzSpecialParticles.csv +++ b/options/MintDalitzSpecialParticles.csv @@ -45,4 +45,5 @@ 9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,1 ,-,-, , 998136, 0, ,R,rhoOmega6 ,?? 1.272E+03 ,7.0E+00,7.0E+00,9.0E+01 ,2.0E+01,2.0E+01,1/2, ,1 ,+, ,F, 998200, +, ,R,Ka ,uS 1.272E+03 ,7.0E+00,7.0E+00,9.0E+01 ,2.0E+01,2.0E+01,1/2, ,1 ,+, ,F, 998201, +, ,R,Kb ,uS +1.86484E+03 ,1.7E-01,1.7E-01,1.605E-09 ,6.0E-12,6.0E-12,1/2, ,0 ,-, ,F, 998421, 0, ,R,D~ ,cU *** diff --git a/options/example_glass.opt b/options/example_glass.opt new file mode 100644 index 00000000000..29e8e8baad6 --- /dev/null +++ b/options/example_glass.opt @@ -0,0 +1,17 @@ +EventType D0 K0S0 pi+ pi- + +D0{K(0)*(1430)+[GLASS]{K0S0,pi+},pi-} 2 1 0 2 0 0 + +K(0)*(1430)+::GLASS::a 0 0.113 0.006 +K(0)*(1430)+::GLASS::r 0 -33.800 1.800 +K(0)*(1430)+::GLASS::R 2 1.000 0.000 +K(0)*(1430)+::GLASS::F 0 0.960 0.007 +K(0)*(1430)+::GLASS::phiR 0 -109.700 2.600 +K(0)*(1430)+::GLASS::phiF 0 0.100 0.300 + +K(0)*(1430)bar-::GLASS::a = K(0)*(1430)+::GLASS::a +K(0)*(1430)bar-::GLASS::r = K(0)*(1430)+::GLASS::r +K(0)*(1430)bar-::GLASS::R = K(0)*(1430)+::GLASS::R +K(0)*(1430)bar-::GLASS::F = K(0)*(1430)+::GLASS::F +K(0)*(1430)bar-::GLASS::phiR = K(0)*(1430)+::GLASS::phiR +K(0)*(1430)bar-::GLASS::phiF = K(0)*(1430)+::GLASS::phiF diff --git a/options/mass_width.csv b/options/mass_width.csv index 436b4bb6124..648339d34fb 100644 --- a/options/mass_width.csv +++ b/options/mass_width.csv @@ -584,9 +584,9 @@ 1.3828E+03 ,4.0E-01,4.0E-01,3.58E+01 ,8.0E-01,8.0E-01,1 , ,3/2 ,+, ,F, 3224, +,4,R,Sigma(1385) ,uus 1.38370E+03 ,1.0E+00,1.0E+00,3.6E+01 ,5.0E+00,5.0E+00,1 , ,3/2 ,+, ,F, 3214, 0,4,R,Sigma(1385) ,uds 1.3872E+03 ,5.0E-01,5.0E-01,3.94E+01 ,2.1E+00,2.1E+00,1 , ,3/2 ,+, ,F, 3114, -,4,R,Sigma(1385) ,dds -1.480E+03 ,1.5E+01,1.5E+01,6.0E+01 ,1.5E+01,1.5E+01,1 , ,? ,?, ,F, , +,1,S,Sigma(1480) ,uus -1.480E+03 ,1.5E+01,1.5E+01,6.0E+01 ,1.5E+01,1.5E+01,1 , ,? ,?, ,F, , 0,1,S,Sigma(1480) ,uds -1.480E+03 ,1.5E+01,1.5E+01,6.0E+01 ,1.5E+01,1.5E+01,1 , ,? ,?, ,F, , -,1,S,Sigma(1480) ,dds +1.480E+03 ,1.5E+01,1.5E+01,6.0E+01 ,1.5E+01,1.5E+01,1 , ,1/2 ,+, ,F, , +,1,S,Sigma(1480) ,uus +1.480E+03 ,1.5E+01,1.5E+01,6.0E+01 ,1.5E+01,1.5E+01,1 , ,1/2 ,+, ,F, , 0,1,S,Sigma(1480) ,uds +1.480E+03 ,1.5E+01,1.5E+01,6.0E+01 ,1.5E+01,1.5E+01,1 , ,1/2 ,+, ,F, , -,1,S,Sigma(1480) ,dds 1.572E+03 ,4.0E+00,4.0E+00,7.9E+01 ,3.0E+01,3.0E+01,1 , ,? ,?, ,F, , +,2,S,Sigma(1560) ,uus 1.572E+03 ,4.0E+00,4.0E+00,7.9E+01 ,3.0E+01,3.0E+01,1 , ,? ,?, ,F, , 0,2,S,Sigma(1560) ,uds 1.572E+03 ,4.0E+00,4.0E+00,7.9E+01 ,3.0E+01,3.0E+01,1 , ,? ,?, ,F, , -,2,S,Sigma(1560) ,dds diff --git a/src/EventType.cpp b/src/EventType.cpp index 79f89b6a0b3..6f6d9cc613f 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -68,7 +68,7 @@ std::map EventType::getEventFormat( const bool& outputNames size_t s = include_energy ? 4 : 3; for ( unsigned int ip = 0; ip < size(); ++ip ) { std::string stub = - outputNames ? "_" + std::to_string( ip + 1 ) + "_" + m_particleNamesPickled[ip] : std::to_string( ip ); + outputNames ? "_" + std::to_string( ip + 1 ) + "_" + m_particleNamesPickled[ip] : std::to_string( ip ); if( include_energy ) returnValue[stub + "_E"] = s * ip + 3; returnValue[stub + "_Px"] = s * ip + 0; returnValue[stub + "_Py"] = s * ip + 1; @@ -138,49 +138,34 @@ EventType EventType::conj( const bool& headOnly, const bool& dontConjHead ) cons std::vector EventType::defaultProjections(const size_t& nBins) const { - bool useRootLabelling = NamedParameter( "EventType::UseRootTEX", false ); std::string defaultObservable = NamedParameter( "EventType::Observable", "mass2"); - - std::vector axes; - std::string gevcccc = useRootLabelling ? "GeV^{2}/c^{4}" : "\\mathrm{GeV}^{2}/c^{4}"; - std::string gevcc = useRootLabelling ? "GeV/c^{2}" : "\\mathrm{GeV}/c^{2}"; + std::vector projections; for ( size_t r = 2; r < size(); ++r ) { /// loop over sizes /// std::vector> combR = nCr( size(), r ); - for ( auto& indices : combR ) { - auto mm = minmax( indices, true ); - if( defaultObservable == "mass2" ) - axes.emplace_back( [indices]( const Event& evt ) { return evt.s( indices ); }, - "s" + vectorToString( indices ), - "s_{" + label( indices, useRootLabelling ) + "}", nBins, - ( mm.first - 0.05 ) , ( mm.second + 0.05 ) , gevcccc ); - else if( defaultObservable == "mass" ){ - axes.emplace_back( [indices]( const Event& evt ) { return sqrt( evt.s( indices ) ); }, - "m" + vectorToString( indices ), - "m_{" + label( indices, useRootLabelling ) + "}", nBins, - mm.first > 0.05 ? sqrt(mm.first - 0.05) :0 , sqrt( mm.second + 0.05 ) , gevcc ); - } - } + for ( auto& indices : combR ) + projections.emplace_back( projection(nBins, indices, defaultObservable ) ); } - return axes; + return projections; } -Projection EventType::projection(const size_t& nBins, const std::vector& indices) const +Projection EventType::projection(const size_t& nBins, const std::vector& indices, const std::string& observable) const { - std::string defaultObservable = NamedParameter( "EventType::Observable", "mass2"); - auto mm = minmax( indices, true ); - std::string gevcccc = "\\mathrm{GeV}^{2}/c^{4}"; - std::string gevcc = "\\mathrm{GeV}/c^{2}"; - if( defaultObservable == "mass2" ) - return Projection( [indices]( const Event& evt ) { return evt.s( indices ); }, - "s" + vectorToString( indices ), - "s_{" + label( indices ) + "}", nBins, - ( mm.first - 0.05 ) , ( mm.second + 0.05 ) , gevcccc ); - else if( defaultObservable == "mass" ){ - return Projection( [indices]( const Event& evt ) { return sqrt( evt.s( indices ) ); }, - "m" + vectorToString( indices ), - "m_{" + label( indices ) + "}", nBins, - mm.first > 0.05 ? sqrt(mm.first - 0.05) :0 , sqrt( mm.second + 0.05 ) , gevcc ); - } + bool useRootLabelling = NamedParameter("EventType::UseRootTEX", false ); + auto mm = minmax(indices, true); + std::string gevcccc = useRootLabelling ? "GeV^{2}/c^{4}" : "\\mathrm{GeV}^{2}/c^{4}"; + std::string gevcc = useRootLabelling ? "GeV/c^{2}" : "\\mathrm{GeV}/c^{2}"; + if( observable == "mass2" ) + return Projection( [indices]( const Event& evt ) { return evt.s( indices ); }, + "s" + vectorToString( indices ), + "s_{" + label( indices ) + "}", nBins, + ( mm.first - 0.05 ) , ( mm.second + 0.05 ) , gevcccc ); + else if( observable == "mass" ){ + return Projection( [indices]( const Event& evt ) { return sqrt( evt.s( indices ) ); }, + "m" + vectorToString( indices ), + "m_{" + label( indices ) + "}", nBins, + mm.first > 0.05 ? sqrt(mm.first - 0.05) :0 , sqrt( mm.second + 0.05 ) , gevcc ); + } + return Projection(); } bool EventType::operator==( const EventType& other ) const diff --git a/src/Lineshapes/GLASS.cpp b/src/Lineshapes/GLASS.cpp new file mode 100644 index 00000000000..0db9cc3a9a2 --- /dev/null +++ b/src/Lineshapes/GLASS.cpp @@ -0,0 +1,35 @@ +#include + +#include "AmpGen/Expression.h" +#include "AmpGen/Factory.h" +#include "AmpGen/Lineshapes.h" +#include "AmpGen/ParticleProperties.h" +#include "AmpGen/ParticlePropertiesList.h" +#include "AmpGen/Units.h" + +using namespace AmpGen; +using namespace AmpGen::fcn; + +DEFINE_LINESHAPE( GLASS ) +{ + const auto props = ParticlePropertiesList::get( particleName ); + Expression mass = Parameter( particleName + "_mass", props->mass() ); + Expression width0 = Parameter( particleName + "_width", props->width() ); + Expression s0 = mass*mass; + Expression a = Parameter( particleName + "::GLASS::a", 2.07 ); + Expression r = Parameter( particleName + "::GLASS::r", 3.32 ); + Expression phi_R = Parameter( particleName + "::GLASS::phiR", 0.00 ); + Expression phi_F = Parameter( particleName + "::GLASS::phiF", 0.00 ); + Expression A_R = Parameter( particleName + "::GLASS::R", 1.00 ); + Expression A_F = Parameter( particleName + "::GLASS::F", 1.00 ); + Expression q2 = Q2(s, s1, s2); + Expression q20 = Q2(s0, s1, s2); + Expression q = safe_sqrt( q2 ); + Expression rho = q/sqrt(s); + Expression rho0 = sqrt(q20)/mass; + Expression gamma = width0 * rho / rho0; + Expression dF = make_cse(M_PI * phi_F/180. + atan(2*a*q/(2 + a*r*q2))); + Expression dR = make_cse(M_PI * phi_R/180. + atan(mass*gamma / (s0 - s))); + Expression i = Constant(0,1); + return R*sin(dR)*exp(i*(dR+2*dF)) + F*sin(dF)*exp(i*dF); +} diff --git a/src/Lineshapes/Photon.cpp b/src/Lineshapes/Photon.cpp new file mode 100644 index 00000000000..4f241116a44 --- /dev/null +++ b/src/Lineshapes/Photon.cpp @@ -0,0 +1,11 @@ +#include "AmpGen/Lineshapes.h" +#include "AmpGen/ParticlePropertiesList.h" + +using namespace AmpGen; + +DEFINE_LINESHAPE( Photon ) +{ + auto props = ParticlePropertiesList::get( particleName ); + Expression mass = Parameter( particleName + "_mass", props->mass() ); + return 1. / ( s - mass*mass ); +} diff --git a/src/Minimiser.cpp b/src/Minimiser.cpp index f0bea2c20f9..a0d84924bea 100644 --- a/src/Minimiser.cpp +++ b/src/Minimiser.cpp @@ -65,7 +65,7 @@ void Minimiser::prepare() { std::string algorithm = NamedParameter( "Minimiser::Algorithm", "Hesse"); size_t maxCalls = NamedParameter( "Minimiser::MaxCalls" , 100000); - double tolerance = NamedParameter( "Minimiser::Tolerance" , 0.1); + double tolerance = NamedParameter( "Minimiser::Tolerance" , 1); m_printLevel = NamedParameter( "Minimiser::PrintLevel", 4); if ( m_minimiser != nullptr ) delete m_minimiser; m_minimiser = new Minuit2::Minuit2Minimizer(algorithm.c_str() ); diff --git a/src/Particle.cpp b/src/Particle.cpp index 5d46c7fea0c..bb6283f4b68 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -81,10 +81,8 @@ Particle::Particle( const std::string& decayString, const std::vector( items[it] ) ); - + for( auto& modifier : m_modifiers ) parseModifier( modifier ); + for( size_t it = 1; it < items.size(); ++it ) m_daughters.push_back( std::make_shared( items[it] ) ); m_props = ParticlePropertiesList::get( m_name ); pdgLookup(); auto fs = getFinalStateParticles( false ); @@ -100,7 +98,6 @@ Particle::Particle( const std::string& decayString, const std::vectorisStateGood(); - if ( !isStateGood() ) { ERROR( "Amplitude " << decayString << " not configured correctly" ); } @@ -180,11 +177,11 @@ void Particle::pdgLookup() return; } if ( m_lineshape == "BW" || m_usesDefaultLineshape ) { - if ( m_name.find( "NonRes" ) != std::string::npos || m_props->width() < 1e-3 ) - m_lineshape = "FormFactor"; + if ( m_name.find("NonRes") != std::string::npos || m_props->width() < 1e-3 ) m_lineshape = "FormFactor"; + if ( m_name == "gamma0" ) m_lineshape = "Photon"; m_usesDefaultLineshape = true; - } else - m_usesDefaultLineshape = false; + } + else m_usesDefaultLineshape = false; m_parity = m_props->P(); if ( !isdigit( m_props->J()[0] ) ) { ERROR( "Spin not recognised! : " << m_name << " J = " << m_props->J() ); @@ -314,12 +311,11 @@ Particle Particle::quasiStableTree() const { Particle returnVal( m_name ); for ( auto& d : m_daughters ) { - auto qTree = d->quasiStableTree(); - if ( d->isQuasiStable() ) { - returnVal.addDaughter( std::make_shared( qTree ) ); - } else { - for ( auto& dp : qTree.daughters() ) returnVal.addDaughter( dp ); - } + auto qTree = d->quasiStableTree(); + if( qTree.daughters().size() == 0 || (qTree.isQuasiStable() && m_daughters.size() != 1 ) ) + returnVal.addDaughter( std::make_shared(qTree) ); + else + for( auto& it : qTree.daughters() ) returnVal.addDaughter(it); } returnVal.sortDaughters(); returnVal.makeUniqueString(); @@ -511,7 +507,7 @@ Tensor Particle::externalSpinTensor(const int& polState, DebugSymbols* db ) cons Expression N = make_cse(1./(m*(pE + m))); if( polState == 1 ) return -Tensor({1.+ z *pX*N, 1i + z*pY*N, z*pZ*N , z*m })/sqrt(2); if( polState == -1 ) return Tensor({1.+ zb*pX*N, -1i + zb*pY*N, zb*pZ*N , zb*m })/sqrt(2); - if( polState == -1 ) return Tensor({pX*pZ*N , pY*pZ*N, 1 + pZ*pZ*N, pZ/m }); + if( polState == 0 ) return Tensor({pX*pZ*N , pY*pZ*N, 1 + pZ*pZ*N, pZ/m }); } if( m_props->twoSpin() == 1 && m_spinBasis == "Weyl" ){ Expression n = fcn::sqrt( 2 * pP*(pP+pZ) ); @@ -536,7 +532,8 @@ Tensor Particle::externalSpinTensor(const int& polState, DebugSymbols* db ) cons if(id < 0 && polState == -1 ) return norm * Tensor({ pZ/(pE+m), z/(pE+m) , 1 ,0 }); if(id < 0 && polState == 1 ) return norm * Tensor({ zb/(pE+m),-pZ/(pE+m) , 0 ,1 }); } - WARNING("Spin tensors not implemented for spin J = " << m_props->twoSpin() << " / 2 m = " << m_polState << " " << m_name ); + std::string js = m_props->isBoson() ? std::to_string(m_props->twoSpin()/2) : std::to_string(m_props->twoSpin()) +"/2"; + WARNING("Spin tensors not implemented for spin J = " << js << "; m = " << m_polState << " " << m_name ); return Tensor( std::vector( {1.} ), Tensor::dim(0) ); } @@ -717,7 +714,7 @@ bool Particle::isStable() const { return m_daughters.size() == 0; } bool Particle::isQuasiStable() const { - return props()->width() < ParticlePropertiesList::getMe()->quasiStableThreshold(); + return props()->width() < ParticlePropertiesList::getMe()->quasiStableThreshold() && name() != "gamma0"; } unsigned int Particle::orbital() const { return m_orbital; } int Particle::polState() const { return m_polState; } diff --git a/src/Projection.cpp b/src/Projection.cpp index 186b8622e9e..5a08fbaa0a9 100644 --- a/src/Projection.cpp +++ b/src/Projection.cpp @@ -9,6 +9,8 @@ using namespace AmpGen; +Projection::Projection(){} + Projection::Projection( const std::function& fcn, const std::string& name, const std::string& xAxisTitle, const size_t& nBins, const double& min, const double& max, diff --git a/src/Vertex.cpp b/src/Vertex.cpp index 4c0dfd756b8..ceb1b9a27f4 100644 --- a/src/Vertex.cpp +++ b/src/Vertex.cpp @@ -428,24 +428,24 @@ DEFINE_VERTEX( f_rS_P1 ) DEFINE_VERTEX( S_ff_S ) { Tensor::Index a; - return Bar( V2 )(a) * V1(a); + return Bar(V2)(a) * V1(a); } DEFINE_VERTEX( S_ff_S1 ) { Tensor::Index a,b; - return Bar( V2 )(a) * Gamma[4](a,b) * V1(b); + return Bar(V2)(a) * Gamma[4](a,b) * V1(b); } DEFINE_VERTEX( V_ff_P ) { Tensor::Index a,b ; - return Bar( V2 )(a) * Gamma4Vec()(mu,a,b) * V1(b); + return Bar(V2)(a) * Gamma4Vec()(mu,a,b) * V1(b); } DEFINE_VERTEX( V_ff_P1 ) { Tensor::Index a,b,c ; - return Bar( V2 )(a) * Gamma[4](a,b) * Gamma4Vec()(mu,b,c) * V1(c); + return Bar(V2)(a) * Gamma[4](a,b) * Gamma4Vec()(mu,b,c) * V1(c); } diff --git a/src/Wigner.cpp b/src/Wigner.cpp index d39334b33c3..06f0f880e46 100644 --- a/src/Wigner.cpp +++ b/src/Wigner.cpp @@ -168,6 +168,8 @@ std::vector AmpGen::calculate_recoupling_constants( f.factor = sqrt( (2.*L + 1. )/( 2.*J + 1. ) ); f.cg1 = CG(L ,0 ,S ,m1-m2,J,m1-m2); f.cg2 = CG(j1,m1,j2,-m2 ,S,m1-m2); + // f.cg1 = CG(L ,0 ,S ,m1-m2,J,M); + // f.cg2 = CG(j1,m1,j2,-m2 ,S,M); f.p = sqrt( (2*L + 1 )/(2*J+1) ); f.factor *= f.cg1 * f.cg2; if( f.factor != 0 ) rt.push_back(f); diff --git a/test/test_Particle.cpp b/test/test_Particle.cpp new file mode 100644 index 00000000000..771aaa2cee5 --- /dev/null +++ b/test/test_Particle.cpp @@ -0,0 +1,18 @@ +#define BOOST_TEST_DYN_LINK + +#define BOOST_TEST_MODULE "Particle" + +#include +#include "AmpGen/Particle.h" + +BOOST_AUTO_TEST_CASE( Particle_quasiStableTree ) +{ + auto d1 = AmpGen::Particle("D~0{D0{K*(892)0{K+,pi-},rho(770)0{pi+,pi-}}}"); + auto d2 = AmpGen::Particle("B+{D0{K*(892)0{K+,pi-},rho(770)0{pi+,pi-}},K+}"); + auto d3 = AmpGen::Particle("B+{D~0{D0{K*(892)0{K+,pi-},rho(770)0{pi+,pi-}}},K+}"); + BOOST_CHECK( d1.quasiStableTree().decayDescriptor() == "D~0{K+,pi+,pi-,pi-}" ); + BOOST_CHECK( d2.quasiStableTree().decayDescriptor() == "B+{D0{K+,pi+,pi-,pi-},K+}" ); + BOOST_CHECK( d3.quasiStableTree().decayDescriptor() == "B+{D~0{K+,pi+,pi-,pi-},K+}" ); +} + + diff --git a/test/test_ParticleProperties.cpp b/test/test_ParticleProperties.cpp index 84085df71b2..010e5624c79 100644 --- a/test/test_ParticleProperties.cpp +++ b/test/test_ParticleProperties.cpp @@ -1,6 +1,6 @@ #define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MODULE "Expression" +#define BOOST_TEST_MODULE "ParticlePropertiesList" #include #include "AmpGen/ParticlePropertiesList.h" From 963b86260dd5ac1edcf4b5e66edd768e8c3503c2 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 29 Apr 2019 11:33:41 +0200 Subject: [PATCH 056/250] Fix GLASS so it compiles, but it still doesn't work :( --- options/example_glass.opt | 7 +++++++ src/Lineshapes/GLASS.cpp | 19 ++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/options/example_glass.opt b/options/example_glass.opt index 29e8e8baad6..69babd9d999 100644 --- a/options/example_glass.opt +++ b/options/example_glass.opt @@ -9,6 +9,13 @@ K(0)*(1430)+::GLASS::F 0 0.960 0.007 K(0)*(1430)+::GLASS::phiR 0 -109.700 2.600 K(0)*(1430)+::GLASS::phiF 0 0.100 0.300 +# K(0)*(1430)+::GLASS::a 0 2.070 0.006 +# K(0)*(1430)+::GLASS::r 0 3.320 1.800 +# K(0)*(1430)+::GLASS::R 2 1.000 0.000 +# K(0)*(1430)+::GLASS::F 0 1.000 0.007 +# K(0)*(1430)+::GLASS::phiR 0 0.000 2.600 +# K(0)*(1430)+::GLASS::phiF 0 0.000 0.300 + K(0)*(1430)bar-::GLASS::a = K(0)*(1430)+::GLASS::a K(0)*(1430)bar-::GLASS::r = K(0)*(1430)+::GLASS::r K(0)*(1430)bar-::GLASS::R = K(0)*(1430)+::GLASS::R diff --git a/src/Lineshapes/GLASS.cpp b/src/Lineshapes/GLASS.cpp index 0db9cc3a9a2..64075e13256 100644 --- a/src/Lineshapes/GLASS.cpp +++ b/src/Lineshapes/GLASS.cpp @@ -12,6 +12,7 @@ using namespace AmpGen::fcn; DEFINE_LINESHAPE( GLASS ) { + WARNING("GLASS lineshape does not work as expected"); const auto props = ParticlePropertiesList::get( particleName ); Expression mass = Parameter( particleName + "_mass", props->mass() ); Expression width0 = Parameter( particleName + "_width", props->width() ); @@ -20,16 +21,24 @@ DEFINE_LINESHAPE( GLASS ) Expression r = Parameter( particleName + "::GLASS::r", 3.32 ); Expression phi_R = Parameter( particleName + "::GLASS::phiR", 0.00 ); Expression phi_F = Parameter( particleName + "::GLASS::phiF", 0.00 ); - Expression A_R = Parameter( particleName + "::GLASS::R", 1.00 ); - Expression A_F = Parameter( particleName + "::GLASS::F", 1.00 ); + Expression R = Parameter( particleName + "::GLASS::R", 1.00 ); + Expression F = Parameter( particleName + "::GLASS::F", 1.00 ); Expression q2 = Q2(s, s1, s2); Expression q20 = Q2(s0, s1, s2); Expression q = safe_sqrt( q2 ); Expression rho = q/sqrt(s); Expression rho0 = sqrt(q20)/mass; Expression gamma = width0 * rho / rho0; - Expression dF = make_cse(M_PI * phi_F/180. + atan(2*a*q/(2 + a*r*q2))); - Expression dR = make_cse(M_PI * phi_R/180. + atan(mass*gamma / (s0 - s))); + Expression dF = make_cse(M_PI*phi_F/180. + atan(2*a*q/(2 + a*r*q2))); + Expression dR = make_cse(M_PI*phi_R/180. + atan(mass*gamma / (s0 - s))); Expression i = Constant(0,1); - return R*sin(dR)*exp(i*(dR+2*dF)) + F*sin(dF)*exp(i*dF); + ADD_DEBUG(s, dbexpressions ); + ADD_DEBUG(s0, dbexpressions ); + ADD_DEBUG(dF, dbexpressions ); + ADD_DEBUG(dR, dbexpressions ); + ADD_DEBUG(phi_F, dbexpressions ); + ADD_DEBUG(phi_R, dbexpressions ); + ADD_DEBUG(gamma, dbexpressions ); + + return R*sin(dR)*exp(i*dR)*exp(2*i*dF) + F*sin(dF)*exp(i*dF); } From a221a646619f0e28402cf059edb0d0fc74ae97d0 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 15 May 2019 17:39:49 +0200 Subject: [PATCH 057/250] Improved CP conjugation in Particle, improved threading in CoherentSum --- AmpGen/CoherentSum.h | 3 +- AmpGen/EventList.h | 7 +-- AmpGen/EventType.h | 2 +- AmpGen/Generator.h | 30 +++++----- AmpGen/Particle.h | 26 +++++---- AmpGen/PhaseSpace.h | 2 + AmpGen/Utilities.h | 2 +- apps/Debugger.cpp | 59 +++++++++---------- apps/Fitter.cpp | 2 - examples/FitterWithPolarisation.cpp | 2 +- options/Dbar02piKpipi.opt | 4 +- options/mass_width.csv | 4 +- src/AmplitudeRules.cpp | 13 +++-- src/CoherentSum.cpp | 49 +++++++--------- src/EventType.cpp | 4 ++ src/Lineshapes/BW.cpp | 1 - src/Lineshapes/LASS.cpp | 3 +- src/Particle.cpp | 87 +++++++++++++++-------------- src/PhaseSpace.cpp | 6 +- 19 files changed, 156 insertions(+), 150 deletions(-) diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index 6321ac1ec65..d3803e611d3 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -75,7 +75,8 @@ namespace AmpGen std::map> getGroupedAmplitudes(); Bilinears norms() const { return m_normalisations ; } - + + protected: std::vector> m_matrixElements; ///< Vector of (expanded) matrix elements Bilinears m_normalisations; ///< Normalisation integrals diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index c0800963a5e..0b7c997acee 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -18,9 +18,9 @@ #include #include -#ifdef __USE_OPENMP__ -#include -#endif +// #ifdef __USE_OPENMP__ +// #include +// #endif namespace AmpGen { @@ -106,7 +106,6 @@ namespace AmpGen return size; } } - template unsigned int extendEvent( const std::string& name, FUNCTOR func ) { diff --git a/AmpGen/EventType.h b/AmpGen/EventType.h index e9687fa950f..13ad9ede5b3 100644 --- a/AmpGen/EventType.h +++ b/AmpGen/EventType.h @@ -44,7 +44,7 @@ namespace AmpGen size_t size() const; size_t dof() const; std::string operator[]( const size_t& index ) const; - + std::string decayDescriptor() const; std::string label( const size_t& index, bool isRoot = true ) const; std::string label( const std::vector& index, bool isRoot = true ) const; std::vector defaultProjections(const size_t& nBins) const; diff --git a/AmpGen/Generator.h b/AmpGen/Generator.h index 9f146fd8e2e..42779b8594e 100644 --- a/AmpGen/Generator.h +++ b/AmpGen/Generator.h @@ -12,11 +12,11 @@ namespace AmpGen class Generator { private: - EventType m_eventType; - PHASESPACE m_gps; - unsigned int m_generatorBlock = {5000000}; - TRandom* m_rnd = {gRandom}; - bool m_normalise = {true}; + EventType m_eventType; + PHASESPACE m_gps; + size_t m_generatorBlock = {5000000}; + TRandom* m_rnd = {gRandom}; + bool m_normalise = {true}; public: template @@ -32,7 +32,7 @@ namespace AmpGen m_rnd = rand; m_gps.setRandom( m_rnd ); } - void fillEventListPhaseSpace( EventList& list, const unsigned int& N, unsigned int cacheSize = 0 ) + void fillEventListPhaseSpace( EventList& list, const size_t& N, const size_t& cacheSize = 0 ) { fillEventListPhaseSpace( list, N, cacheSize, []( const Event& evt ) { return 1; } ); } @@ -40,7 +40,7 @@ namespace AmpGen void setNormFlag( const bool& normSetting ) { m_normalise = normSetting; } template - void fillEventListPhaseSpace( EventList& list, const unsigned int& N, const unsigned int& cacheSize, HARD_CUT cut ) + void fillEventListPhaseSpace( EventList& list, const size_t& N, const size_t& cacheSize, HARD_CUT cut ) { unsigned int rejected = 0; #ifdef DEBUGLEVEL @@ -61,20 +61,20 @@ namespace AmpGen << " time = " << time ); } template - void fillEventList( PDF& pdf, EventList& list, const unsigned int& N ) + void fillEventList( PDF& pdf, EventList& list, const size_t& N ) { fillEventList( pdf, list, N, []( const Event& evt ) { return 1; } ); } template - void fillEventList( PDF& pdf, EventList& list, const unsigned int& N, HARD_CUT cut ) + void fillEventList( PDF& pdf, EventList& list, const size_t& N, HARD_CUT cut ) { if ( m_rnd == nullptr ) { ERROR( "Random generator not set!" ); return; } double normalisationConstant = m_normalise ? 0 : 1; - unsigned int size0 = list.size(); + size_t size0 = list.size(); auto tStartTotal = std::chrono::high_resolution_clock::now(); pdf.reset( true ); while ( list.size() - size0 < N ) { @@ -121,20 +121,22 @@ namespace AmpGen std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); INFO( "Generated " << N << " events in " << time << " ms" ); } - template - EventList generate( PDF& pdf, const unsigned int& nEvents ) + template ::value>::type> + EventList generate(PDF& pdf, const size_t& nEvents ) { EventList evts( m_eventType ); fillEventList( pdf, evts, nEvents ); return evts; } - EventList generate( const unsigned int& nEvents, const size_t& cacheSize=0 ) + // template ::value>::type> + EventList generate(const size_t& nEvents, const size_t& cacheSize=0) { EventList evts( m_eventType ); fillEventListPhaseSpace( evts, nEvents, cacheSize ); return evts; } - }; template class PDFWrapper { diff --git a/AmpGen/Particle.h b/AmpGen/Particle.h index 2b0306fc9da..42af4908a84 100644 --- a/AmpGen/Particle.h +++ b/AmpGen/Particle.h @@ -93,14 +93,6 @@ namespace AmpGen Similar to other components of AmpGen, Particles will rarely be constructed in the C++ context, and will instead be instantiated dynamically at runtime from a user supplied options file. */ class ParticleProperties; - //struct zFrame { - // /// Frame where parent is at rest, particle 0 is along the z-axis - // Tensor operator(const std::vector& indices)() const - // { - // - // } - //}; - class Particle { private: @@ -116,8 +108,8 @@ namespace AmpGen unsigned int m_spinConfigurationNumber = {0}; ///< Spin configuration quantum number 'S' unsigned int m_minL = {0}; ///< Minimum orbital angular momentum bool m_isHead = {true}; ///< Flag that particle is head of decay chain - bool m_isStateGood = {true}; ///< Flag to check the decay is well-formed bool m_usesDefaultLineshape = {false}; ///< Flag to check if default shape is used + bool m_isStateGood = {true}; ///< Flag to check the decay is well-formed std::vector> m_daughters; ///< Array of daughter particles std::vector m_modifiers; ///< Additional modifiers for amplitude std::string m_spinFormalism = {""}; ///< Spin formalism to use for this particle (global) @@ -145,18 +137,25 @@ namespace AmpGen /// @constructor Constructor that takes a decay descriptor as an argument and a list of final state particles to match to the event type. Constructs the entire decay tree. Particle( const std::string& decayString, const std::vector& finalStates = {}, const bool& orderDaughters = true ); + /// @function (Quasi) Constructor that returns the (quasi)CP conjugated amplitude. The full behaviour of the amplitude is made more complicated by the ordering convention. + Particle conj(bool invertHead = true, bool reorder = true); + void setOrbital( const unsigned int& orbital ); void setLineshape( const std::string& lineshape ); void setDaughter( const Particle& particle, const unsigned int& index ); void setTop( bool state = true ); void setIndex( const unsigned int& index, const bool& setOri = false ); + void clearDecayProducts(); void addModifier( const std::string& mod ); void parseModifier( const std::string& mod ); void setOrdering( const std::vector& ordering ); + void setName(const std::string& name); void addDaughter( const std::shared_ptr& particle ); void setPolarisationState( const int& state ); - std::pair orbitalRange( const bool& converseParity = true ) const; ///< Range of possible orbital angular momenta between decay products + + /// @function Returns the range of orbital angular momentum between the decay products + std::pair orbitalRange( const bool& converseParity = true ) const; std::vector> spinOrbitCouplings( const bool& conserveParity = true ) const; stdx::optional attribute(const std::string& key) const; const ParticleProperties* props() const; @@ -165,7 +164,6 @@ namespace AmpGen int parity() const; int finalStateParity() const; int polState() const; - int conjugate( bool invertHead = false , bool reorder = true); double mass() const; double spin() const; double S() const; @@ -208,9 +206,12 @@ namespace AmpGen /// @function Decay descriptor formatted as LaTeX for this decay. std::string texLabel( const bool& printHead = false, const bool& recurse=true ) const; - /// @function Returns the ``quasi'' CP Quantum number for this decay + /// @function Returns the ``quasi'' CP Quantum number for this decay, see the Particle int quasiCP() const; + /// @function Returns the C quantum number for this decay + int C() const; + /// @function Return the eventType for this decay (i.e. the initial and final state particles) EventType eventType() const; @@ -270,6 +271,7 @@ namespace AmpGen /// @function matches Check the matching between two decay chains, according to the MatchState enum. unsigned int matches( const Particle& other ) const; }; + std::ostream& operator<<( std::ostream& os, const Particle& particle ); } // namespace AmpGen #endif diff --git a/AmpGen/PhaseSpace.h b/AmpGen/PhaseSpace.h index 090badfc489..d44a8386635 100644 --- a/AmpGen/PhaseSpace.h +++ b/AmpGen/PhaseSpace.h @@ -17,12 +17,14 @@ namespace AmpGen * which saves a large amount of CPU. Further modified to remove the dependencies on TLorentzVector * and to only use the AmpGen::Event classes, and to add the option to include a time dependence. */ + class Particle; class PhaseSpace { public: PhaseSpace() = default; PhaseSpace( const EventType& type, TRandom* rand = gRandom ); + PhaseSpace( const Particle& type, TRandom* rand = gRandom ); ~PhaseSpace() = default; bool setDecay( const double& m0, const std::vector& mass ); diff --git a/AmpGen/Utilities.h b/AmpGen/Utilities.h index 72208c55c0f..d2b82ad5b8e 100644 --- a/AmpGen/Utilities.h +++ b/AmpGen/Utilities.h @@ -12,7 +12,7 @@ #include #include #include -#include +//#include #include "AmpGen/MsgService.h" #include "AmpGen/MetaUtils.h" diff --git a/apps/Debugger.cpp b/apps/Debugger.cpp index 411d1dc3fb7..0c2877497a3 100644 --- a/apps/Debugger.cpp +++ b/apps/Debugger.cpp @@ -45,45 +45,40 @@ void invertParity( Event& event, const size_t& nParticles) } } -int invert_parameter( AmpGen::MinuitParameter* param, MinuitParameterSet& mps ) +void invert( MinuitParameter* param, MinuitParameterSet& mps ) { const std::string name = param->name(); - size_t pos = 0; - std::string prefix = ""; - std::string new_name = name; - int sgn = 1; - if ( name.find( "::" ) != std::string::npos ) { - pos = name.find( "::" ); - auto props = AmpGen::ParticlePropertiesList::get( name.substr( 0, pos ), true ); - if ( props != nullptr ) new_name = props->anti().name() + name.substr( pos ); - } else { - auto tokens = split( name, '_' ); + size_t pos=0; + std::string new_name = name; + int sgn=1; + if( name.find("::") != std::string::npos ){ + pos = name.find("::"); + auto props = AmpGen::ParticlePropertiesList::get( name.substr(0,pos), true ); + if( props != 0 ) new_name = props->anti().name() + name.substr(pos); + } + else { + auto tokens=split(name,'_'); std::string reOrIm = *tokens.rbegin(); - std::string prefix = ""; std::string name = tokens[0]; - if ( tokens.size() == 3 ) { - prefix = tokens[0]; - name = tokens[1]; + if ( reOrIm == "Re" || reOrIm == "Im" ){ + Particle test = Particle(name).conj(); + sgn = reOrIm == "Re" ? test.quasiCP() : 1; + new_name = test.uniqueString() +"_"+reOrIm; } - if ( reOrIm == "Re" || reOrIm == "Im" ) { - std::vector final_state_ordering; - AmpGen::Particle test( name, final_state_ordering ); - sgn = test.conjugate( true ); - if ( reOrIm == "Re" ) sgn = 1; - new_name = ( prefix != "" ? prefix + "_" : "" ) + test.uniqueString() + "_" + reOrIm; - } else if ( tokens.size() == 2 ) { - auto props = AmpGen::ParticlePropertiesList::get( name ); - if ( props != nullptr ) new_name = props->anti().name() + "_" + tokens[1]; + else if( tokens.size() == 2 ) { + auto props = AmpGen::ParticlePropertiesList::get( name ); + if( props != 0 ) new_name = props->anti().name() + "_" + tokens[1]; } } - DEBUG( param->name() << " → " << new_name << " sgn = " << sgn ); - mps.map().erase( param->name() ); - param->setName( new_name ); - mps.map().emplace( param->name(), param ); - if ( sgn == -1 ) param->setCurrentFitVal( param->mean() + M_PI ); - return sgn; + if( param->name() != new_name && mps.find(new_name) == nullptr ){ + mps.map().erase( param->name() ); + param->setName( new_name ); + mps.map().emplace( param->name(), param ); + } + if( sgn == -1 ) param->setCurrentFitVal( -1 * param->mean() ); } + template void print( const Event& event, const MatrixElements& matrixElements, bool verbose ) { for ( auto& mE : matrixElements ) { @@ -127,8 +122,8 @@ int main( int argc, char** argv ) AmpGen::MinuitParameterSet MPS; MPS.loadFromStream(); if ( NamedParameter( "conj", false ) == true ) { - eventType = eventType.conj( false ); - for ( auto& param : MPS ) invert_parameter( param, MPS ); + eventType = eventType.conj(false); + for ( auto& param : MPS ) invert( param, MPS ); } INFO( "EventType = " << eventType ); diff --git a/apps/Fitter.cpp b/apps/Fitter.cpp index a7d0a07ec48..4a264c5f77a 100644 --- a/apps/Fitter.cpp +++ b/apps/Fitter.cpp @@ -93,10 +93,8 @@ template FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& MPS ) { INFO( "Type = " << typeof() ); - auto time_wall = std::chrono::high_resolution_clock::now(); auto time = std::clock(); - pdf.setEvents( data ); Minimiser mini( pdf, &MPS ); diff --git a/examples/FitterWithPolarisation.cpp b/examples/FitterWithPolarisation.cpp index 25aad8ae32a..35f6dafb0af 100644 --- a/examples/FitterWithPolarisation.cpp +++ b/examples/FitterWithPolarisation.cpp @@ -100,7 +100,7 @@ int main( int argc, char* argv[] ) /* Generate events to normalise the PDF with. This can also be loaded from a file, which will be the case when efficiency variations are included. Default number of normalisation events is 5 million. */ - EventList eventsMC = Generator<>(evtType, &rndm).generate(5e6); + EventList eventsMC = Generator<>(evtType, &rndm).generate(int(5e6)); sig.setMC( eventsMC ); diff --git a/options/Dbar02piKpipi.opt b/options/Dbar02piKpipi.opt index 6e254ae3811..b3ee7777480 100644 --- a/options/Dbar02piKpipi.opt +++ b/options/Dbar02piKpipi.opt @@ -46,8 +46,8 @@ PiPi20[kMatrix.pole.1]{pi+,pi-} PiPi20[kMatrix.pole.0]{pi+,pi-} 2 0.291 0.007 2 165.8 1.3 PiPi20[kMatrix.prod.0]{pi+,pi-} 2 0.117 0.002 2 170.5 1.2 a(1)(1260)-[D;GSpline.EFF]{rho(770)0{pi+,pi-},pi-} 2 0.582 0.011 2 -152.8 1.2 -a(1)(1260)-_mass 2 1.19505 0.00105 2 -a(1)(1260)-_radius 2 1.70000 0.00000 2 +a(1)(1260)-_mass 2 1.19505 0.00105 +a(1)(1260)-_radius 2 1.70000 0.00000 a(1)(1260)-_width 2 0.42201 0.00210 K(1)(1270)+[GSpline.EFF]{rho(770)0{pi+,pi-},K+} 2 1.000 0.000 2 0.0 0.0 K(1)(1270)+[GSpline.EFF]{rho(1450)0{pi+,pi-},K+} 2 2.016 0.026 2 -119.5 0.9 diff --git a/options/mass_width.csv b/options/mass_width.csv index 648339d34fb..4c90987eb09 100644 --- a/options/mass_width.csv +++ b/options/mass_width.csv @@ -666,8 +666,8 @@ 1.32171E+03 ,7.0E-02,7.0E-02,4.04E-12 ,4.0E-14,4.0E-14,1/2, ,1/2 ,+, ,F, 3312, -,4,R,Xi ,dss 1.53180E+03 ,3.2E-01,3.2E-01,9.1E+00 ,5.0E-01,5.0E-01,1/2, ,3/2 ,+, ,F, 3324, 0,4,R,Xi(1530) ,uss 1.5350E+03 ,6.0E-01,6.0E-01,9.9E+00 ,1.7E+00,1.9E+00,1/2, ,3/2 ,+, ,F, 3314, -,4,R,Xi(1530) ,dss -1.6240E+03 ,3.0E+00,3.0E+00,22.5 ,-1 ,-1 ,1/2, ,? ,?, ,F, , 0,1,S,Xi(1620) ,uss -1.6240E+03 ,3.0E+00,3.0E+00,22.5 ,-1 ,-1 ,1/2, ,? ,?, ,F, , -,1,S,Xi(1620) ,dss +1.6240E+03 ,3.0E+00,3.0E+00,22.5 ,-1 ,-1 ,1/2, ,3/2 ,+, ,F, , 0,1,S,Xi(1620) ,uss +1.6240E+03 ,3.0E+00,3.0E+00,22.5 ,-1 ,-1 ,1/2, ,3/2 ,+, ,F, , -,1,S,Xi(1620) ,dss 1.6900E+03 ,1.0E+01,1.0E+01,-1 ,-1 ,-1 ,1/2, ,? ,?, ,F, , 0,3,D,Xi(1690) ,uss 1.6900E+03 ,1.0E+01,1.0E+01,-1 ,-1 ,-1 ,1/2, ,? ,?, ,F, , -,3,D,Xi(1690) ,dss 1.823E+03 ,5.0E+00,5.0E+00,2.40E+01 ,1.5E+01,1.0E+01,1/2, ,3/2 ,-, ,F, 13324, 0,3,D,Xi(1820) ,uss diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index 11be23a6451..3b2f5db229c 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -164,12 +164,10 @@ void CouplingConstant::print() const for ( auto& coupling : couplings ) INFO( coupling.first->name() << " x exp(i" << coupling.second->name() ); } -std::vector< std::pair > AmplitudeRules::getMatchingRules( - const EventType& type, const std::string& prefix ){ - +std::vector> AmplitudeRules::getMatchingRules(const EventType& type, const std::string& prefix ) +{ auto rules = rulesForDecay( type.mother() ); std::vector> rt; - for ( auto& rule : rules ) { if ( rule.prefix() != prefix ) continue; std::vector> tmpParticles; @@ -200,6 +198,13 @@ std::vector< std::pair > AmplitudeRules::getMatchin tmpParticles = newTmpParticles; } while ( tmpParticles.size() != 0 ); } + rt.erase( std::remove_if( std::begin(rt), std::end(rt), [](auto& p){ return !p.first.isStateGood(); } ), rt.end() ); + auto end = std::end(rt); + for (auto it = rt.begin(); it != end; ++it) { + auto dd = it->first.decayDescriptor(); + end = std::remove_if(it + 1, end, [dd](auto p){ return p.first.decayDescriptor() == dd;} ); + } + rt.erase(end, rt.end()); return rt; } diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index ce72c724f82..b5ea9e74bc2 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -26,11 +26,11 @@ #include "AmpGen/ProfileClock.h" #ifdef __USE_OPENMP__ -#include + #include #endif using namespace AmpGen; - +CoherentSum::CoherentSum(){} CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, const std::string& prefix ) : m_protoAmplitudes( mps ) , m_evtType( type ) @@ -41,38 +41,26 @@ CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, , m_prefix( prefix ) { auto amplitudes = m_protoAmplitudes.getMatchingRules( m_evtType, prefix); - for( auto& amp : amplitudes ) addMatrixElement( amp, mps ); - m_isConstant = isFixedPDF(mps); - m_normalisations.resize( m_matrixElements.size(), m_matrixElements.size() ); - ThreadPool tp(8); - for( auto& mE: m_matrixElements ) - tp.enqueue( [&]{ CompilerWrapper().compile( mE.pdf, this->m_objCache); } ); -} - -void CoherentSum::addMatrixElement( std::pair& particleWithCouplingConstant, const MinuitParameterSet& mps ) -{ - auto& protoParticle = particleWithCouplingConstant.first; - auto& coupling = particleWithCouplingConstant.second; - if ( !protoParticle.isStateGood() ) return; - const std::string name = protoParticle.uniqueString(); - DebugSymbols dbExpressions; - INFO( name ); - for ( auto& mE : m_matrixElements ) { - if ( name == mE.decayTree.uniqueString() ) return; + for( auto& amp : amplitudes ) INFO( amp.first.decayDescriptor() ); + m_matrixElements.resize( amplitudes.size() ); + m_normalisations.resize( m_matrixElements.size(), m_matrixElements.size() ); + ThreadPool tp(1); + for(size_t i = 0; i < m_matrixElements.size(); ++i){ + tp.enqueue( [i,this,&mps,&litudes]{ + m_matrixElements[i] = TransitionMatrix( amplitudes[i].first, amplitudes[i].second, mps, this->m_evtType.getEventFormat(), this->m_dbThis); + CompilerWrapper().compile( m_matrixElements[i].pdf, this->m_objCache); } ); } - m_matrixElements.emplace_back(protoParticle, coupling, mps, m_evtType.getEventFormat(), m_dbThis); + m_isConstant = isFixedPDF(mps); } - + void CoherentSum::prepare() { if ( m_weightParam != nullptr ) m_weight = m_weightParam->mean(); if ( m_isConstant && m_prepareCalls != 0 ) return; transferParameters(); - std::vector changedPdfIndices; ProfileClock clockEval; bool printed = false; - for ( unsigned int i = 0; i < m_matrixElements.size(); ++i ) { auto& pdf = m_matrixElements[i].pdf; pdf.prepare(); @@ -129,15 +117,15 @@ void CoherentSum::debug( const Event& evt, const std::string& nameMustContain ) if ( nameMustContain == "" ) for ( auto& pdf : m_matrixElements ) { auto A = pdf(evt); - INFO( std::setw(70) << pdf.decayTree.uniqueString() << " A = [ " - << std::real(A) << " " << std::imag(A) << " ] g = [ " - << std::real(pdf.coupling()) << " " << std::imag(pdf.coupling()) << " ]" ); + INFO( std::setw(70) << pdf.decayTree.uniqueString() + << " A = [ " << std::real(A) << " " << std::imag(A) + << " ] g = [ "<< std::real(pdf.coupling()) << " " << std::imag(pdf.coupling()) << " ]" ); if( m_dbThis ) pdf.pdf.debug( evt ); } else for ( auto& pdf : m_matrixElements ) if ( pdf.pdf.name().find( nameMustContain ) != std::string::npos ) pdf.pdf.debug( evt ); - + if( evt.cacheSize() != 0 ) INFO( "Pdf = " << prob_unnormalised( evt ) ); } @@ -292,7 +280,10 @@ void CoherentSum::reset( bool resetEvents ) m_prepareCalls = 0; m_lastPrint = 0; for ( auto& mE : m_matrixElements ) mE.addressData = 999; - if ( resetEvents ) m_events = nullptr; + if ( resetEvents ){ + m_events = nullptr; + m_integrator = Integrator<10>(); + } } void CoherentSum::setEvents( EventList& list ) diff --git a/src/EventType.cpp b/src/EventType.cpp index 6f6d9cc613f..e9412c6b2c1 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -232,3 +232,7 @@ std::string convertTeXtoROOT( std::string input ) return input; } +std::string EventType::decayDescriptor() const +{ + return mother()+"{" + vectorToString(m_particleNames,",") +"}" ; +} diff --git a/src/Lineshapes/BW.cpp b/src/Lineshapes/BW.cpp index a58c2cfe665..6f8e8b8c417 100644 --- a/src/Lineshapes/BW.cpp +++ b/src/Lineshapes/BW.cpp @@ -74,7 +74,6 @@ DEFINE_LINESHAPE( BW ) return kf * BW; } - DEFINE_LINESHAPE( SBW ) { auto props = ParticlePropertiesList::get( particleName ); diff --git a/src/Lineshapes/LASS.cpp b/src/Lineshapes/LASS.cpp index eae25a1eb3f..1a6404df832 100644 --- a/src/Lineshapes/LASS.cpp +++ b/src/Lineshapes/LASS.cpp @@ -32,13 +32,14 @@ DEFINE_LINESHAPE( LASS ) Expression tan_phi2 = mass*gamma / (s0 - s); Expression phase = atan(tan_phi1) + atan(tan_phi2); - ADD_DEBUG(sin(phase) * exp( i * phase ) / rho, dbexpressions ); Expression bw = ( mass * width0 ) / ( rho0 * ( s0 -s -i*mass*gamma ) ); Expression nrPhaseShift = ( 2 + a * r * q2 + i * 2*a*q ) / ( 2+a*r*q2 - i*2*a*q ); Expression NR = 2*a*sqrt(s)/( 2 + a*r*q*q -2*i*a*q ); ADD_DEBUG(nrPhaseShift*bw, dbexpressions ); ADD_DEBUG(NR, dbexpressions ); ADD_DEBUG(NR + bw*nrPhaseShift, dbexpressions ); + ADD_DEBUG(sin(phase) * exp( i * phase ) , dbexpressions ); + ADD_DEBUG(sin(phase) * exp( i * phase ) / rho, dbexpressions ); // Takes the splitting of the LASS into a "resonant" and "nonresonant" // component from Laura++, as a better implementation of the "gLASS" lineshape diff --git a/src/Particle.cpp b/src/Particle.cpp index bb6283f4b68..0a29b7d6dd0 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -166,7 +166,6 @@ std::string Particle::vertexName() const auto vx= m_props->spinName() + "_" + m_daughters[0]->m_props->spinName() + m_daughters[1]->m_props->spinName() + "_" + orbitalString; - return vx; } @@ -183,15 +182,12 @@ void Particle::pdgLookup() } else m_usesDefaultLineshape = false; m_parity = m_props->P(); - if ( !isdigit( m_props->J()[0] ) ) { - ERROR( "Spin not recognised! : " << m_name << " J = " << m_props->J() ); - } + if ( !isdigit( m_props->J()[0] ) ) ERROR( "Spin not recognised! : " << m_name << " J = " << m_props->J() ); if( m_defaultModifier != "" && m_lineshape.find(".") == std::string::npos ){ m_lineshape = m_lineshape + "." + m_defaultModifier; } bool isStrong = quarks() == daughterQuarks(); DEBUG( m_name << " is decaying via " << ( isStrong ? "strong" : "electroweak" ) << " interactions; P = " << props()->P() ); - if ( m_name.find( "NonRes" ) != std::string::npos ) isStrong = true; m_minL = m_daughters.size() == 2 ? orbitalRange( isStrong ).first : 0; if ( m_daughters.size() == 2 ) { @@ -199,14 +195,13 @@ void Particle::pdgLookup() << " name = " << m_name << " d0 = " << m_daughters[0]->name() << " d1 = " << m_daughters[1]->name() ); } - if ( m_orbital == 0 ) m_orbital = m_minL; //// define in ground state unless specified /// - + if ( m_orbital == 0 ) m_orbital = m_minL; // define in ground state unless specified for ( auto& d : m_daughters ) d->setTop( false ); } Tensor Particle::P() const { - Tensor momentum( std::vector( {0., 0., 0., 0.} ), std::vector( {4} ) ); + Tensor momentum( std::vector( {0., 0., 0., 0.} ), Tensor::dim(4) ); if ( isStable() ) { if ( m_index != 999 ) { const std::string index = std::to_string( m_index ); @@ -273,12 +268,7 @@ std::string Particle::makeUniqueString() { std::string modifier = modifierString(); if ( m_daughters.size() != 0 ) { - std::string val = m_name + modifier + "{"; - for ( unsigned int i = 0; i < m_daughters.size(); ++i ) { - m_daughters[i]->makeUniqueString(); - val += m_daughters[i]->uniqueString() + ( i == m_daughters.size() - 1 ? "}" : "," ); - } - m_uniqueString = val; + m_uniqueString = m_name + modifier + "{" + vectorToString( m_daughters, ",", [](auto& d){ return d->makeUniqueString() ;} ) +"}"; } else { m_uniqueString = m_name + modifier ; } @@ -288,7 +278,6 @@ std::string Particle::makeUniqueString() std::vector> Particle::getFinalStateParticles( const bool& sort ) const { std::vector> ffs; - for ( auto daughter : m_daughters ) { if ( daughter->isStable() ) { ffs.push_back( daughter ); @@ -368,7 +357,11 @@ void Particle::setOrdering( const std::vector& ordering ) finalStateParticles[i]->setIndex( ordering[i] ); } } -void Particle::addDaughter( const std::shared_ptr& particle ) { m_daughters.push_back( particle ); } +void Particle::addDaughter( const std::shared_ptr& particle ) +{ + m_daughters.push_back( particle ); + m_uniqueString = makeUniqueString(); +} Tensor Particle::transitionMatrix( DebugSymbols* db ) { @@ -623,33 +616,20 @@ std::string Particle::texLabel( const bool& printHead, const bool& recurse ) con void Particle::sortDaughters() { - std::stable_sort( m_daughters.begin(), m_daughters.end(), []( auto& A, auto& B ) { return *A < *B; } ); + std::stable_sort( m_daughters.begin(), m_daughters.end(), + []( auto& A, auto& B ) { return *A < *B; } ); + m_uniqueString = makeUniqueString(); } - -int Particle::conjugate( bool invertHead , bool reorder ) +Particle Particle::conj( bool invertHead , bool reorder ) { - int sgn = 1; - DEBUG( "Conjugating flavour of " << m_name ); - if ( m_props == nullptr ) ERROR( "Particle properties not found for " << m_name ); - if ( ( !m_isHead || invertHead ) && m_props->hasDistinctAnti() ) { - DEBUG( "Trying to conjugate: " << m_name ); - m_props = ParticlePropertiesList::get( -m_props->pdgID() ); - m_name = m_props->name(); - m_parity = m_props->P(); - } - sgn *= pow( -1, m_orbital ); - if ( m_parity == -1 - && m_daughters.size() == 2 - && std::abs(daughter(0)->props()->pdgID()) == std::abs(daughter(1)->props()->pdgID()) - && daughter(0)->props()->pdgID() != daughter(1)->props()->pdgID() ) { - sgn *= -1; - } - for ( auto& d : m_daughters ) sgn *= d->conjugate( invertHead ); - if( reorder ) sortDaughters(); - std::string oldUniqueString = m_uniqueString; - m_uniqueString = makeUniqueString(); - DEBUG( "Conjugate : " << oldUniqueString << " to " << m_uniqueString << " sgn = " << sgn ); - return sgn; + Particle cp(*this); + cp.clearDecayProducts(); + const ParticleProperties* p = ( !m_isHead || invertHead ) && m_props->hasDistinctAnti() ? ParticlePropertiesList::get( -m_props->pdgID() ) : m_props; + cp.setName( p->name() ); + for( auto& d : m_daughters ) cp.addDaughter( std::make_shared(d->conj(invertHead,reorder)) ); + if( reorder ) cp.sortDaughters(); + cp.pdgLookup(); + return cp; } QuarkContent Particle::quarks() const @@ -665,12 +645,24 @@ QuarkContent Particle::daughterQuarks() const } Expression Particle::massSq() const { return isStable() ? mass() * mass() : make_cse( dot( P(), P() ) ); } + +void Particle::clearDecayProducts() +{ + m_daughters.clear(); +} + void Particle::addModifier( const std::string& mod ) { m_modifiers.push_back( mod ); parseModifier( mod ); m_uniqueString = makeUniqueString(); } +void Particle::setName(const std::string& name) +{ + m_name = name; + m_props = ParticlePropertiesList::get(name); + m_parity = m_props->P(); +} void Particle::setTop( bool state ) { m_isHead = state; } void Particle::setIndex( const unsigned int& index, const bool& setOri ) { @@ -697,7 +689,7 @@ int Particle::finalStateParity() const bool Particle::conservesParity( unsigned int L ) const { - return parity() == daughter( 0 )->parity() * daughter( 1 )->parity() * ( L % 2 == 0 ? 1 : -1 ); + return parity() == daughter(0)->parity() * daughter(1)->parity() * ( L % 2 == 0 ? 1 : -1 ); } std::string Particle::topologicalString() const @@ -806,6 +798,13 @@ int Particle::quasiCP() const return prod; } +int Particle::C() const +{ + auto prod = ( props()->C() == 0 ? 1 : props()->C() ); + for( auto& d : m_daughters ) prod *= d->C(); + return prod; +} + stdx::optional Particle::attribute(const std::string& key) const { for( auto& modifier : m_modifiers ){ @@ -814,3 +813,7 @@ stdx::optional Particle::attribute(const std::string& key) const } return stdx::nullopt; } + +std::ostream& AmpGen::operator<<( std::ostream& os, const Particle& particle ){ + return os << particle.decayDescriptor(); +} diff --git a/src/PhaseSpace.cpp b/src/PhaseSpace.cpp index 6caf2832251..246b8b17f66 100644 --- a/src/PhaseSpace.cpp +++ b/src/PhaseSpace.cpp @@ -10,6 +10,7 @@ #include "AmpGen/ParticlePropertiesList.h" #include "AmpGen/Types.h" #include "AmpGen/MsgService.h" +#include "AmpGen/Particle.h" #include "TRandom.h" const Int_t kMAXP = 18; @@ -24,12 +25,15 @@ PhaseSpace::PhaseSpace( const EventType& type, TRandom* rand ) : m_decayTime = 6.582119514 / ( ParticlePropertiesList::get( type.mother() )->width() * pow( 10, 13 ) ); } +PhaseSpace::PhaseSpace( const Particle& particle, TRandom* rand ) : + PhaseSpace( particle.eventType(), rand ) {} + double PhaseSpace::q( double m, double m1, double m2 ) const { return 0.5 * sqrt( m*m - 2*m1*m1 - 2*m2*m2 + (m1*m1-m2*m2)*(m1*m1-m2*m2)/(m*m) ); } -Event PhaseSpace::makeEvent(const size_t& cacheSize) +Event PhaseSpace::makeEvent(const size_t& cacheSize) { std::array rno; std::array pd; From eb15951099ba44b49a0932dee6c9e43b47ae87d5 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 16 May 2019 11:54:47 +0200 Subject: [PATCH 058/250] Add quantum-correlated generator example --- AmpGen/AmplitudeRules.h | 1 + AmpGen/CoherentSum.h | 1 + AmpGen/EventList.h | 6 +- AmpGen/EventType.h | 6 +- AmpGen/OptionsParser.h | 4 +- doc/release.notes | 2 + examples/QcGenerator.cpp | 390 ++++++++++++++++++++++++++++++++ examples/SignalOnlyFitter.cpp | 8 +- examples/qc_options_example.opt | 47 ++++ src/CoherentSum.cpp | 8 + src/EventType.cpp | 15 ++ src/OptionsParser.cpp | 5 +- 12 files changed, 480 insertions(+), 13 deletions(-) create mode 100644 examples/QcGenerator.cpp create mode 100644 examples/qc_options_example.opt diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index a3b53f6c6fa..84a823cefd8 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -101,6 +101,7 @@ namespace AmpGen } const RT operator()(const Event& event) const { return pdf(event.address() ); } + const RT operator()(const Event& event, const size_t& cacheOffset) const { return pdf(event.address() + cacheOffset); } const std::string decayDescriptor() const { return decayTree.decayDescriptor() ; } Particle decayTree; diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index d3803e611d3..eadb935daf2 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -53,6 +53,7 @@ namespace AmpGen complex_t getVal( const Event& evt ) const; complex_t getVal( const Event& evt, const std::vector& cacheAddresses ) const; complex_t getValNoCache( const Event& evt ) const; + complex_t getValNoCache( const Event& evt, const size_t& offset ) const; void transferParameters(); void prepare(); diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 0b7c997acee..377129b5009 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -18,9 +18,9 @@ #include #include -// #ifdef __USE_OPENMP__ -// #include -// #endif +#ifdef __USE_OPENMP__ +#include +#endif namespace AmpGen { diff --git a/AmpGen/EventType.h b/AmpGen/EventType.h index 13ad9ede5b3..ca00861dbb4 100644 --- a/AmpGen/EventType.h +++ b/AmpGen/EventType.h @@ -32,6 +32,7 @@ namespace AmpGen EventType( const std::vector&, const bool& isTD = false ); std::map getEventFormat( const bool& outputNames = false ) const; + std::pair count(const size_t& index) const; ///< Count the number of particles with name. std::pair minmax( const std::vector& indices, bool isGeV = false ) const; std::vector> getBosePairs() const; std::vector masses() const; @@ -49,7 +50,7 @@ namespace AmpGen std::string label( const std::vector& index, bool isRoot = true ) const; std::vector defaultProjections(const size_t& nBins) const; Projection projection(const size_t& nBins, const std::vector& indices, const std::string& observable = "mass2") const; - + bool operator==( const EventType& other ) const; bool has( const std::string& name ) const; EventType conj( const bool& headOnly = 0, const bool& dontConjHead = 0 ) const; @@ -57,7 +58,8 @@ namespace AmpGen void setMotherMass( const double& mass ){ m_motherMass = mass ; } void extendEventType( const std::string& branch ); std::function symmetriser() const; - std::pair dim() const; ///< calculates the number of spin indices accociated with the initial and final state, i.e. the rank of the relevant transition matrix. + ///< calculates the number of spin indices associated with the initial and final state, i.e. the rank of the relevant transition matrix. + std::pair dim() const; }; std::ostream& operator<<( std::ostream& os, const EventType& type ); } // namespace AmpGen diff --git a/AmpGen/OptionsParser.h b/AmpGen/OptionsParser.h index c1bd3449a15..21f4cbcef53 100644 --- a/AmpGen/OptionsParser.h +++ b/AmpGen/OptionsParser.h @@ -17,10 +17,10 @@ namespace AmpGen static OptionsParser* getMe(); static bool printHelp(); - static void setArgs( int argc, char** argv ); + static void setArgs( int argc, char** argv, const std::string& description="" ); static void setArg( const std::string& arg ); void addArg( const std::string& arg ); - void setCommandLineArgs( int argc, char** argv ); + void setCommandLineArgs( int argc, char** argv, const std::string& description =""); void import( const std::string& fName ); iterator find( const std::string& name ); iterator begin(); diff --git a/doc/release.notes b/doc/release.notes index 08a6f9a3dd8..9ef40f10271 100644 --- a/doc/release.notes +++ b/doc/release.notes @@ -3,6 +3,8 @@ ! Responsible : Tim Evans ! Purpose : !----------------------------------------------------------------------------- + - Improved thread support for CoherentSum + - Add examples/QcGenerator for Ψ(3770) decays !=================== AmpGen v1r1 2019-03-22 ================== ! 2019-03-22 - Tim Evans - Added support for fitting more general final states, i.e. with multiple fermions, photons etc. diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp new file mode 100644 index 00000000000..108ab615b26 --- /dev/null +++ b/examples/QcGenerator.cpp @@ -0,0 +1,390 @@ +#include "AmpGen/CoherentSum.h" +#include "AmpGen/Generator.h" +#include "AmpGen/EventType.h" +#include "AmpGen/NamedParameter.h" +#include "AmpGen/Kinematics.h" +#include "AmpGen/OptionsParser.h" +#include "AmpGen/ProfileClock.h" +#include "AmpGen/ParticlePropertiesList.h" +#include "AmpGen/MinuitParameterSet.h" + +#include +#include +#include +#include +#include + +using namespace AmpGen; +using namespace std::complex_literals; + +struct DTEvent { + AmpGen::Event signal; + AmpGen::Event tag; + double prob; + DTEvent() : signal(0,0,0), tag(0,0,0) {}; + DTEvent( const AmpGen::Event& signal, const AmpGen::Event& tag ) : signal(signal), tag(tag) {}; + void set( const AmpGen::Event& s1, const AmpGen::Event& s2 ) { signal.set(s1); tag.set(s2); }; + void invertParity(){ + for( size_t i = 0 ; i < signal.size(); ++i ) if( i % 4 != 3 ) signal[i] *= -1; + for( size_t i = 0 ; i < tag.size(); ++i ) if( i % 4 != 3 ) tag[i] *= -1; + } +}; + +struct DTEventList : public std::vector { + AmpGen::EventType m_sigType; + AmpGen::EventType m_tagType; + DTEventList( const AmpGen::EventType& signal, const AmpGen::EventType& tag ) : m_sigType(signal), m_tagType(tag) {} + std::string particleName(const AmpGen::EventType& type, const size_t& j); + TTree* tree(const std::string& name); +}; + +class DTYieldCalculator { + public: + DTYieldCalculator(const double& productionCrossSection = 3260) : + productionCrossSection(productionCrossSection){} + + double operator()(const double& lumi, + const AmpGen::EventType& t_signal, + const AmpGen::EventType& t_tag, + const bool& print = false); + double bf( const AmpGen::EventType& type ) const; + private: + double productionCrossSection; + std::map getKeyed( const std::string& name ); + std::map branchingRatios = {getKeyed("BranchingRatios")}; + std::map efficiencies = {getKeyed("Efficiencies")}; +}; + +void add_CP_conjugate( MinuitParameterSet& mps ); + +template struct normalised_pdf { + PDF pdf; + complex_t norm; + normalised_pdf(){}; + normalised_pdf(const EventType& type, MinuitParameterSet& mps, const DTYieldCalculator& yc) : pdf(type, mps) + { + ProfileClock pc; + auto normEvents = Generator(type).generate(1e6); + double n =0; + pdf.prepare(); + #pragma omp parallel for reduction(+:n) + for(size_t i =0; imean() * M_PI/180. ); + pc.stop(); + INFO("Time to construct: " << pc << "[ms], norm = " << norm ); + } + complex_t operator()(const Event& event){ return norm * pdf.getValNoCache(event); } +}; + +struct ModelStore { + MinuitParameterSet* mps; + DTYieldCalculator yieldCalculator; + std::map> genericModels; + ModelStore(MinuitParameterSet* mps, const DTYieldCalculator& yc) : mps(mps), yieldCalculator(yc) {} + template normalised_pdf& get(const EventType& type, std::map>& container) + { + auto key = type.decayDescriptor(); + if( container.count(key) == 0 ) container[key] = normalised_pdf(type,*mps, yieldCalculator); + return container[key]; + } + template normalised_pdf& find(const EventType& type); +}; + +template class Psi3770 { + private: + EventType m_signalType; + EventType m_tagType; + normalised_pdf& m_signal; + normalised_pdf& m_signalBar; + normalised_pdf& m_tag; + normalised_pdf& m_tagBar; + PhaseSpace m_signalPhsp; + PhaseSpace m_tagPhsp; + PhaseSpace m_headPhsp; + bool m_printed = {false}; + size_t m_blockSize = {1000000}; + public: + template std::tuple + z(T& t1, T& t2, const EventType& type) const + { + double n1(0), n2(0), zR(0), zI(0); + auto normEvents = Generator(type).generate(m_blockSize); + #pragma omp parallel for reduction(+:zR,zI,n1,n2) + for(size_t i = 0; i < m_blockSize; ++i){ + auto p1 = t1(normEvents[i]); + auto p2 = t2(normEvents[i]); + auto f = p2 * std::conj(p1); + zR += std::real(f); + zI += std::imag(f); + n1 += std::norm(p1); + n2 += std::norm(p2); + } + complex_t z2(zR,zI); + auto arg = std::arg(z2); + return std::make_tuple( std::abs(z2/sqrt(n1*n2)), 180 * ( arg > 0 ? arg : 2*M_PI+arg) /M_PI, sqrt(n1/n2) ); + } + Psi3770(ModelStore& models, + const EventType& signalType, + const EventType& tagType) : + m_signalType(signalType) , + m_tagType (tagType) , + m_signal (models.find(m_signalType)), + m_signalBar (models.find(m_signalType.conj(true))), + m_tag (models.find(m_tagType)) , + m_tagBar (models.find(m_tagType.conj(true))) , + m_signalPhsp(m_signalType ) , + m_tagPhsp (m_tagType ) , + m_headPhsp (EventType({"psi(3770)0","D0","Dbar0"})) + { + INFO("Type = " << m_signalType << " x " << m_tagType.conj(true) << "] - [" << m_signalType.conj(true) << " x " << m_tagType << "]"); + auto z1 = z(m_signal, m_signalBar, m_signalType); + auto z2 = z(m_tag , m_tagBar , m_tagType); + INFO( "Signal: R = " << round(std::get<0>(z1),5) << "; δ = " << round(std::get<1>(z1),3) << "° ; r = " << round(std::get<2>(z1),5) ); + INFO( "Tag : R = " << round(std::get<0>(z2),5) << "; δ = " << round(std::get<1>(z2),3) << "° ; r = " << round(std::get<2>(z2),5) ); + } + complex_t operator()( const DTEvent& event ) const { return operator()( event.signal, event.tag ); } + complex_t operator()( const Event& signal, const Event& tag) const { return m_signal(signal)*m_tagBar(tag) - m_signalBar(signal) * m_tag(tag); } + double P(const DTEvent& event) const { return std::norm(operator()(event)); } + double prob_noQC (const DTEvent& event) const { return std::norm(m_signal(event.signal)*m_tagBar(event.tag)) + std::norm(m_signalBar(event.signal)*m_tag(event.tag)); } + DTEvent generatePhaseSpace() { return DTEvent( m_signalPhsp.makeEvent(), m_tagPhsp.makeEvent() ); } + DTEventList generate( const size_t& N ) + { + DTEventList output( m_signalType, m_tagType ); + double norm = -1; + ProfileClock pc; + while( output.size() < N ){ + auto events = generatePHSP(m_blockSize); + if(norm == -1 ){ + for(auto& event : events) if(event.prob > norm ) norm = event.prob; + norm *= 1.5; + INFO("Calculated normalisation of PDF = " << norm ); + } + int currentSize = output.size(); + for( auto& event : events ){ + if( event.prob > norm * gRandom->Uniform() ) output.push_back( event ); + if( output.size() >= N ) break ; + } + INFO( "size = " << output.size() << " / " << N << " efficiency = " << 100 * double(output.size()-currentSize)/double(m_blockSize) ); + } + auto psi_q = PhaseSpace(m_headPhsp); + auto beta = [](const Event& event, const size_t&j){ return sqrt( event[4*j+0]*event[4*j+0] + event[4*j+1]*event[4*j+1] + event[4*j+2]*event[4*j+2] )/event[4*j+3] ; }; + auto p = [](const Event& event, const size_t&j){ return std::make_tuple( event[4*j+0], event[4*j+1], event[4*j+2] ) ; }; + for( auto& event : output ){ + auto psi_event = psi_q.makeEvent(); + boost( event.signal, p(psi_event,0), beta(psi_event,0)); + boost( event.tag , p(psi_event,1), beta(psi_event,1)); + } + pc.stop(); + INFO("Requested: " << N << " events t=" << pc << "[ms]"); + return output; + } + DTEventList generatePHSP(const size_t& N, const bool& eval=true){ + DTEventList output( m_signalType, m_tagType ); + for(size_t x = 0 ; x < m_blockSize; ++x) output.emplace_back( generatePhaseSpace() ); + #pragma omp parallel for + for(size_t i = 0 ; i < m_blockSize; ++i ) output[i].prob = P(output[i]); + return output; + } + double rho() { + double withQC=0; + double withoutQC =0; + DTEventList evts = generatePHSP(m_blockSize, false); + #pragma omp parallel for reduction(+:withQC,withoutQC) + for( size_t x = 0; x("nCores" , hwt , "Number of threads to use"); + double luminosity = NamedParameter("Luminosity" , 818.3 , "Luminosity to generate. Defaults to CLEO-c integrated luminosity."); + size_t nEvents = NamedParameter("nEvents" , 0 , "Can also generate a fixed number of events per tag, if unspecified use the CLEO-c integrated luminosity."); + size_t seed = NamedParameter("Seed" , 0 , "Random seed to use."); + bool poissonYield = NamedParameter("PoissonYield" , true , "Flag to include Poisson fluctuations in expected yields (only if nEvents is not specified)"); + double crossSection = NamedParameter("CrossSection" , 3.26 * 1000 , "Cross section for e⁺e⁻ → Ψ(3770) → DD'"); + std::string output = NamedParameter("Output" , "ToyMC.root" , "File containing output events"); + auto pNames = NamedParameter("EventType" , "" + , "EventType to generate, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(); + auto tags = NamedParameter("TagTypes" , std::string(), "Vector of opposite side tags to generate, in the format \033[3m outputTreeName decayDescriptor \033[0m.").getVector(); + + gRandom = new TRandom3(seed); + omp_set_num_threads( nThreads ); + INFO("Setting " << nThreads << " fixed threads for OpenMP"); + omp_set_dynamic(0); + MinuitParameterSet MPS; + MPS.loadFromStream(); + add_CP_conjugate( MPS ); + EventType signalType( pNames ); + TFile* f = TFile::Open( output.c_str() ,"RECREATE"); + auto yc = DTYieldCalculator(crossSection); + if( nEvents == 0 ) + INFO("Generating events using PDG/efficiencies with luminosity = " << luminosity << " pb⁻¹; σ = " << crossSection << " pb" ); + else INFO("Generating " << nEvents << " per sample"); + ModelStore models(&MPS, yc); + for( auto& tag : tags ){ + auto tokens = split(tag, ' '); + EventType type = Particle(tokens[1], {}, false).eventType(); + double yield_noQC = yc(luminosity,signalType,type,true); + auto generator = Psi3770(models, signalType, type) ; + double rho = generator.rho(); + double yield = nEvents; + if( nEvents == 0 && poissonYield ) yield = gRandom->Poisson(yield_noQC*rho); + if( nEvents == 0 && !poissonYield ) yield = yield_noQC*rho; + INFO( "Tag = " << type << " Expected Yield [incoherent] = " << yield_noQC << " rho = " << rho << " requested = " << yield ); + generator.generate(yield).tree(tokens[0])->Write(); + } + f->Close(); + auto twall_end = std::chrono::high_resolution_clock::now(); + double time_cpu = ( std::clock() - time ) / (double)CLOCKS_PER_SEC; + double tWall = std::chrono::duration( twall_end - time_wall ).count(); + INFO( "Wall time = " << tWall / 1000. ); + INFO( "CPU time = " << time_cpu ); +} + + +void add_CP_conjugate( MinuitParameterSet& mps ) +{ + std::vector tmp; + for( auto& param : mps ){ + const std::string name = param->name(); + size_t pos=0; + std::string new_name = name; + int sgn=1; + if( name.find("::") != std::string::npos ){ + pos = name.find("::"); + auto props = AmpGen::ParticlePropertiesList::get( name.substr(0,pos), true ); + if( props != 0 ) new_name = props->anti().name() + name.substr(pos); + } + else { + auto tokens=split(name,'_'); + std::string reOrIm = *tokens.rbegin(); + std::string name = tokens[0]; + if ( reOrIm == "Re" || reOrIm == "Im" ){ + auto p = Particle( name ).conj(); + sgn = reOrIm == "Re" ? p.quasiCP() : 1; + new_name = p.uniqueString() +"_"+reOrIm; + } + else if( tokens.size() == 2 ) { + auto props = AmpGen::ParticlePropertiesList::get( name ); + if( props != 0 ) new_name = props->anti().name() + "_" + tokens[1]; + } + } + if( mps.map().count( new_name ) == 0 ){ + tmp.push_back( new MinuitParameter(new_name, MinuitParameter::Flag::Float, sgn * param->mean(), param->err(), 0, 0)); + } + } + for( auto& p : tmp ) mps.add( p ); +} + +std::map DTYieldCalculator::getKeyed(const std::string& name) +{ + std::vector things = AmpGen::NamedParameter(name).getVector(); + std::map< std::string , double > branchingRatios; + for( auto& thing : things ){ + auto tokens = AmpGen::split( thing, ' ' ); + AmpGen::Particle p(tokens[0]); + branchingRatios[p.uniqueString()] = stod(tokens[1]); + branchingRatios[p.conj().uniqueString()] = stod(tokens[1]); + } + return branchingRatios; +} + +double DTYieldCalculator::operator()(const double& lumi, + const AmpGen::EventType& t_signal, + const AmpGen::EventType& t_tag, + const bool& print){ + auto statisticalFactor = 2; + if( t_signal == t_tag || t_signal == t_tag.conj(false,true) ) statisticalFactor = 1; + auto signal = AmpGen::Particle(t_signal.decayDescriptor()).uniqueString(); + auto tag = AmpGen::Particle(t_tag.decayDescriptor()).uniqueString(); + auto signalBar = AmpGen::replaceAll( signal, "D0","Dbar0"); + auto tagBar = AmpGen::replaceAll( tag, "D0", "Dbar0"); + auto eff = [this](const std::string& tag) -> double { auto it = efficiencies.find(tag); + if( it == efficiencies.end() ){ + WARNING("Efficiency for final state: " << tag << " not found"); + return 1; + } + return it->second; + }; + double efficiency = eff(signal) * eff(tag); + double br = branchingRatios[signal] * branchingRatios[tagBar] + branchingRatios[signalBar] * branchingRatios[tag]; + double totalDDbar = lumi * productionCrossSection; + if( print ){ + INFO("Expected yield for final state: " << t_signal << " vs " << t_tag ); + INFO("Total DDbar = " << totalDDbar ); + INFO("Efficiency = " << efficiency ); + INFO("BR = " << branchingRatios[signal] <<" x " << branchingRatios[tagBar] + << " + " << branchingRatios[signalBar] << " x " << branchingRatios[tag] + << " = " << br ); + INFO("Total = " << statisticalFactor * totalDDbar * efficiency * br ); + } + return statisticalFactor * totalDDbar * efficiency * br; +} + +double DTYieldCalculator::bf( const AmpGen::EventType& type ) const { + auto p = AmpGen::Particle( type.decayDescriptor() ); + auto it = branchingRatios.find(p.decayDescriptor()); + if( it != branchingRatios.end() ) return it->second; + else { + ERROR("Tag: " << p.decayDescriptor() << " not found in branching ratios"); + return 0; + } +} +std::string DTEventList::particleName(const AmpGen::EventType& type, const size_t& j) +{ + auto count = type.count(j); + if( count.second == 1 ) return programatic_name(type[j]); + return programatic_name(type[j])+std::to_string(count.first); +} +TTree* DTEventList::tree(const std::string& name) +{ + DTEvent tmp(at(0).signal, at(0).tag); + std::vector id_sig(m_sigType.size()), + ids_sig(m_sigType.size()), + id_tag(m_tagType.size()), + ids_tag(m_tagType.size()); + + TTree* outputTree = new TTree(name.c_str(),name.c_str()); + for(size_t i = 0 ; i < m_sigType.size(); ++i ){ + outputTree->Branch((particleName(m_sigType, i)+"_PX").c_str(), &tmp.signal[4*i+0]); + outputTree->Branch((particleName(m_sigType, i)+"_PY").c_str(), &tmp.signal[4*i+1]); + outputTree->Branch((particleName(m_sigType, i)+"_PZ").c_str(), &tmp.signal[4*i+2]); + outputTree->Branch((particleName(m_sigType, i)+"_E").c_str(), &tmp.signal[4*i+3]); + outputTree->Branch((particleName(m_sigType, i)+"_ID").c_str(), &id_sig[i]); + ids_sig[i] = ParticlePropertiesList::get( m_sigType[i] )->pdgID(); + } + for(size_t i = 0 ; i < m_tagType.size(); ++i ){ + outputTree->Branch(("Tag_"+particleName(m_tagType, i)+"_PX").c_str(), &tmp.tag[4*i+0]); + outputTree->Branch(("Tag_"+particleName(m_tagType, i)+"_PY").c_str(), &tmp.tag[4*i+1]); + outputTree->Branch(("Tag_"+particleName(m_tagType, i)+"_PZ").c_str(), &tmp.tag[4*i+2]); + outputTree->Branch(("Tag_"+particleName(m_tagType, i)+"_E").c_str(), &tmp.tag[4*i+3]); + outputTree->Branch(("Tag_"+particleName(m_tagType, i)+"_ID").c_str(), &id_tag[i]); + ids_tag[i] = ParticlePropertiesList::get( m_tagType[i] )->pdgID(); + } + for( auto& evt: *this ){ + bool swap = gRandom->Uniform() > 0.5; + tmp.set( evt.signal, evt.tag ); + if( swap ) tmp.invertParity(); + for(size_t i=0;i< m_sigType.size(); ++i) + id_sig[i] = swap ? -ids_sig[i] : ids_sig[i]; + for(size_t i=0;i< m_tagType.size(); ++i) + id_tag[i] = swap ? -ids_tag[i] : ids_tag[i]; + outputTree->Fill(); + } + return outputTree; +} + +template <> normalised_pdf& ModelStore::find(const EventType& type){ return get(type, genericModels); } + diff --git a/examples/SignalOnlyFitter.cpp b/examples/SignalOnlyFitter.cpp index b7b1cafcbf7..2f2a230b0ae 100644 --- a/examples/SignalOnlyFitter.cpp +++ b/examples/SignalOnlyFitter.cpp @@ -56,13 +56,13 @@ int main( int argc, char* argv[] ) auto pNames = NamedParameter("EventType" , "" , "EventType to fit, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(); - if( dataFile == "" ) FATAL("Must specify input with option " << italic_on << "DataSample" << italic_off ); - if( pNames.size() == 0 ) FATAL("Must specify event type with option " << italic_on << " EventType" << italic_off); - [[maybe_unused]] size_t nThreads = NamedParameter ("nCores" , 8 , "Number of threads to use" ); size_t seed = NamedParameter ("Seed" , 0 , "Random seed used" ); - + + if( dataFile == "" ) FATAL("Must specify input with option " << italic_on << "DataSample" << italic_off ); + if( pNames.size() == 0 ) FATAL("Must specify event type with option " << italic_on << " EventType" << italic_off); + TRandom3 rndm; rndm.SetSeed( seed ); gRandom = &rndm; diff --git a/examples/qc_options_example.opt b/examples/qc_options_example.opt new file mode 100644 index 00000000000..c2c8578d973 --- /dev/null +++ b/examples/qc_options_example.opt @@ -0,0 +1,47 @@ + +EventType D0 K+ pi- pi- pi+ + +TagTypes { "KK D0{K+,K-}" + "KPi D0{K-,pi+}" + "KsPi0 D0{K0S0,pi0}" + "PiK D0{K+,pi-}" + "PiKPiPi D0{K+,pi-,pi-,pi+}" + "KPiPiPi D0{K-,pi+,pi+,pi-}" + } + +Efficiencies { + "D0{K+,K-} 0.57" + "D0{K0S0,pi0} 0.31" + "D0{pi+,pi-} 0.71" + "D0{K-,pi+,pi+,pi-} 0.46" + "D0{K+,pi-,pi-,pi+} 0.46" + "D0{K-,pi+} 0.60" + "D0{K+,pi-} 0.60" +} + +BranchingRatios { + "D0{K+,K-} 0.003970" + "D0{K0S0,pi0} 0.011900" + "D0{pi+,pi-} 0.001407" + "D0{K-,pi+,pi+,pi-} 0.0811" + "D0{K+,pi-,pi-,pi+} 0.000245" + "D0{K-,pi+} 0.0389" + "D0{K+,pi-} 0.0001366" +} + +Import $AMPGENROOT/options/D02piKpipi.opt + +D0{K+,K-} 2 1 0 2 0 0 +Dbar0{K+,K-} 2 1 0 2 0 0 + +D0{pi+,pi-} 2 1 0 2 0 0 +Dbar0{pi+,pi-} 2 1 0 2 0 0 + +D0{K0S0,pi0} 2 1 0 2 0 0 +Dbar0{K0S0,pi0} 2 1 0 2 180 0 + +D0{K-,pi+} 2 1 0 2 0.0 0 +Dbar0{K-,pi+} 2 1 0 2 -191.8 0 + +D0{K+,pi-,pi-,pi+}::strongPhase 2 -130.0 0 #overall phase shift to add to the D0->K+,pi-,pi-,pi+ +Dbar0{K-,pi+,pi+,pi-}::strongPhase = D0{K+,pi-,pi-,pi+}::strongPhase diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index b5ea9e74bc2..feb3726e9aa 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -275,6 +275,14 @@ complex_t CoherentSum::getValNoCache( const Event& evt ) const [&evt]( auto& a, auto& b ){ return a + b.coefficient * b(evt);} ); } +complex_t CoherentSum::getValNoCache(const Event& evt, const size_t& offset) const +{ + return std::accumulate( m_matrixElements.begin(), + m_matrixElements.end(), + complex_t(0,0), + [&evt,&offset]( auto& a, auto& b ){ return a + b.coefficient * b(evt, offset);} ); +} + void CoherentSum::reset( bool resetEvents ) { m_prepareCalls = 0; diff --git a/src/EventType.cpp b/src/EventType.cpp index e9412c6b2c1..9b695d68b1f 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -93,6 +93,21 @@ std::pair EventType::minmax( const std::vector& indices, if ( std::find( indices.begin(), indices.end(), x ) == indices.end() ) max -= mass( x ); return std::pair( min * min / GeV, max * max / GeV ); } +std::pair EventType::count(const size_t& index) const +{ + if( index >= size() ){ + ERROR("Looking for matching particles to index = " << index << " > size of eventType"); + return std::pair(0, 0); + } + std::pair rt(0,0); + for( size_t j = 0 ; j < size(); ++j ){ + if( EventType::operator[](j) == EventType::operator[](index) ){ + rt.second++; + if( j < index ) rt.first++; + } + } + return rt; +} std::vector> EventType::getBosePairs() const { diff --git a/src/OptionsParser.cpp b/src/OptionsParser.cpp index 381e51db1d1..62b606c2ff6 100644 --- a/src/OptionsParser.cpp +++ b/src/OptionsParser.cpp @@ -31,7 +31,7 @@ bool OptionsParser::ignoreThisLine( const std::string& line ) return false; } -void OptionsParser::setCommandLineArgs( int argc, char** argv ) +void OptionsParser::setCommandLineArgs( int argc, char** argv, const std::string& description ) { printSplash(); int x = 0; @@ -60,6 +60,7 @@ void OptionsParser::setCommandLineArgs( int argc, char** argv ) } if( m_printHelp ){ std::cout << bold_on << "Usage: " << bold_off << argv[0] << italic_on << " options_file1.opt options_file2.opt --key1=value1 --key2=value2 ..." << italic_off << std::endl; + if( description != "") std::cout << description << std::endl; std::cout << bold_on << "Options: " << bold_off << std::endl; } } @@ -152,7 +153,7 @@ std::vector OptionsParser::makeParsedStrings( const std::string& li bool OptionsParser::printHelp() { return getMe()->m_printHelp ; } -void OptionsParser::setArgs( int argc, char** argv ){ getMe()->setCommandLineArgs(argc, argv ) ; } +void OptionsParser::setArgs( int argc, char** argv , const std::string& description){ getMe()->setCommandLineArgs(argc, argv, description); } void OptionsParser::setArg( const std::string& arg ){ getMe()->addArg( arg ); } OptionsParser::iterator OptionsParser::find( const std::string& name ) { return m_parsedLines.find( name ); } OptionsParser::iterator OptionsParser::begin() { return m_parsedLines.begin(); } From 33f3257a4bc4132a14c916c7471a2b4fcf1b445d Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 22 May 2019 12:58:18 +0200 Subject: [PATCH 059/250] Start adding improvements from cppcheck, removal of unused code --- AmpGen/AmplitudeRules.h | 14 +- AmpGen/ArgumentPack.h | 58 ++-- AmpGen/BinDT.h | 7 +- AmpGen/CoherenceFactor.h | 196 ------------- AmpGen/CoherentSum.h | 2 - AmpGen/EventList.h | 26 +- AmpGen/MetaUtils.h | 1 - AmpGen/MinuitParameterSet.h | 20 +- AmpGen/Particle.h | 62 +++-- AmpGen/Plots.h | 10 +- AmpGen/Tensor.h | 5 +- CMakeLists.txt | 4 +- apps/Debugger.cpp | 6 +- apps/Fitter.cpp | 10 +- doc/doxyfile | 2 +- doc/release.notes | 3 +- examples/QcGenerator.cpp | 2 +- src/AmplitudeRules.cpp | 112 +++----- src/BinDT.cpp | 102 +------ src/CoherenceFactor.cpp | 525 ----------------------------------- src/CoherentSum.cpp | 9 +- src/EventList.cpp | 12 +- src/EventType.cpp | 2 +- src/ExpressionParser.cpp | 9 +- src/MinuitParameterSet.cpp | 37 +-- src/OptionsParser.cpp | 36 ++- src/Particle.cpp | 8 +- src/Plots.cpp | 37 +++ src/Simplify.cpp | 3 + src/Tensor.cpp | 14 +- src/ThreeBodyCalculators.cpp | 5 +- src/Utilities.cpp | 17 +- src/Vertex.cpp | 86 +----- src/Wigner.cpp | 5 +- test/test_AmplitudeRules.cpp | 55 ++++ test/test_ArgumentPack.cpp | 6 +- 36 files changed, 325 insertions(+), 1183 deletions(-) delete mode 100644 AmpGen/CoherenceFactor.h delete mode 100644 src/CoherenceFactor.cpp create mode 100644 test/test_AmplitudeRules.cpp diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index 84a823cefd8..61f8de8bf10 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -24,7 +24,7 @@ namespace AmpGen class AmplitudeRule { public: - AmplitudeRule( const std::string& reName, const std::map& mapping ); + AmplitudeRule(MinuitParameter* re, MinuitParameter* im); std::string name() const { return m_name; } std::string head() const { return m_particle.name(); } std::string prefix() const { return m_prefix; } @@ -33,11 +33,10 @@ namespace AmpGen friend class AmplitudeRules; private: - std::string m_prefix; - std::string m_name; - MinuitParameter* m_re; - MinuitParameter* m_im; - bool m_isGood; + std::string m_prefix = {""}; + std::string m_name = {""}; + MinuitParameter* m_re = {nullptr}; + MinuitParameter* m_im = {nullptr}; Particle m_particle; }; @@ -50,7 +49,7 @@ namespace AmpGen bool hasDecay( const std::string& head ); std::map> rules(); std::vector> getMatchingRules( - const EventType& type, const std::string& prefix ); + const EventType& type, const std::string& prefix="" ); std::vector processesThatProduce(const Particle& particle) const; private: std::map> m_rules; @@ -68,7 +67,6 @@ namespace AmpGen std::pair operator[]( const size_t& index ) { return couplings[index]; } bool isFixed() const; bool contains( const std::string& name ) const; - void changeSign(); std::vector> couplings; private: diff --git a/AmpGen/ArgumentPack.h b/AmpGen/ArgumentPack.h index 8ac69eb9dec..9dad136ee7c 100644 --- a/AmpGen/ArgumentPack.h +++ b/AmpGen/ArgumentPack.h @@ -12,6 +12,7 @@ namespace AmpGen { struct IArgument { virtual ~IArgument() = default; + }; /** @class Argument @brief Structure to pass "named" parameters to functions. @@ -38,20 +39,20 @@ namespace AmpGen auto entryList = args.getArg().val; \endcode @tparam TYPE Type of the argument, such as a string, a number, a bool etc. - */ - template struct Argument : public IArgument + */ + template + struct Argument : public IArgument { - Argument( const TYPE& x = TYPE() ) : val( x ) {} + template + Argument( T x ) : val(x) {} + Argument() { + if constexpr(std::is_pointer_v) val = nullptr; + else val = TYPE(); + } operator TYPE() const { return val; } TYPE val; }; - - template struct ArgumentPtr : public IArgument - { - ArgumentPtr( TYPE* x = nullptr ) : val( x ) {} - TYPE* val; - }; - + struct File : public IArgument { std::string name; @@ -63,39 +64,30 @@ namespace AmpGen class ArgumentPack { public: - template + template ArgumentPack( const ARGS&... args ) { std::tuple argTuple( args... ); for_each( argTuple, [this]( auto& f ) { m_parameters.emplace_back( makeShared( f ) ); } ); } - template - ARG getArg( const ARG& default_argument = ARG() ) const - { - for ( auto& param : m_parameters ) { - auto ptr = dynamic_cast( param.get() ); - if ( ptr != nullptr ) return *ptr; - } - return default_argument; + template + ARG getArg( const DEFAULT_TYPE& default_argument = DEFAULT_TYPE() ) const + { + for ( auto& param : m_parameters ) { + auto ptr = dynamic_cast( param.get() ); + if ( ptr != nullptr ) return *ptr; } + return ARG(default_argument); + } private: std::vector> m_parameters; }; -#define DECLARE_ARGUMENT( X, Y ) \ - struct X : public AmpGen::Argument { \ - X( const Y& val = Y() ) : AmpGen::Argument( val ){}; \ +#define DECLARE_ARGUMENT(X, Y) \ + struct X : public AmpGen::Argument { \ + template \ + X(Z val) : AmpGen::Argument(val){} \ + X() : AmpGen::Argument(){} \ } - -#define DECLARE_ARGUMENT_PTR( X, Y ) \ - struct X : public AmpGen::ArgumentPtr { \ - X( Y* val = nullptr ) : AmpGen::ArgumentPtr( val ){}; \ - } - -#define DECLARE_ARGUMENT_DEFAULT( X, Y, Z ) \ - struct X : public AmpGen::Argument { \ - X( const Y& val = Z ) : AmpGen::Argument( val ){}; \ - } - } // namespace AmpGen #endif diff --git a/AmpGen/BinDT.h b/AmpGen/BinDT.h index 20b00c73ecb..c8a2fdb271f 100644 --- a/AmpGen/BinDT.h +++ b/AmpGen/BinDT.h @@ -23,12 +23,11 @@ namespace AmpGen { class Event; - #define PACKET_SIZE 22 DECLARE_ARGUMENT(MaxDepth, size_t ); DECLARE_ARGUMENT(MinEvents, size_t ); DECLARE_ARGUMENT(Dim, size_t ); - DECLARE_ARGUMENT_PTR( Stream, std::ifstream ); - DECLARE_ARGUMENT_DEFAULT( Functor, std::function( const Event& )>, nullptr ); + DECLARE_ARGUMENT(Stream, std::ifstream* ); + DECLARE_ARGUMENT(Functor, std::function( const Event& )>); class BinDT { @@ -121,10 +120,8 @@ namespace AmpGen unsigned int getBin( const double* evt ) const; unsigned int size() const; void readFromStream( std::istream& stream ); - void readFromBinary( std::ifstream& stream ); void serialize( std::ofstream& output ); void serialize( const std::string& filename ); - void writeToBinary( std::ofstream& file ); void setQueueOrdering( const std::vector& queueOrdering ){ m_queueOrdering = queueOrdering ; } std::vector>& nodes() { return m_endNodes; } const std::vector>& const_nodes() const { return m_endNodes; } diff --git a/AmpGen/CoherenceFactor.h b/AmpGen/CoherenceFactor.h deleted file mode 100644 index de7638f058b..00000000000 --- a/AmpGen/CoherenceFactor.h +++ /dev/null @@ -1,196 +0,0 @@ -#ifndef AMPGEN_COHERENCEFACTOR_H -#define AMPGEN_COHERENCEFACTOR_H -#include -#include -#include -#include -#include -#include -#include -#include - -#include "AmpGen/BinDT.h" -#include "AmpGen/EventList.h" -#include "AmpGen/EventType.h" -#include "AmpGen/CoherentSum.h" -#include "AmpGen/Integrator.h" -#include "AmpGen/MsgService.h" -#include "AmpGen/Utilities.h" -#include "AmpGen/Types.h" - -namespace AmpGen -{ - class Event; - - struct CoherenceEvent { - std::array values; - complex_t amp1; - complex_t amp2; - real_t weight; - uint64_t flag; - }; - - struct CoherenceCalculator { - CoherentSum* m_pdf1; - CoherentSum* m_pdf2; - Bilinears R; - Bilinears N1; - Bilinears N2; - real_t rTransform; - real_t phiTransform; - CoherenceCalculator() = default; - CoherenceCalculator( CoherentSum* pdf1, CoherentSum* pdf2 ) - : m_pdf1( pdf1 ) - , m_pdf2( pdf2 ) - , R( m_pdf1->size(), m_pdf2->size() ) - , N1( m_pdf1->size(), m_pdf1->size() ) - , N2( m_pdf2->size(), m_pdf2->size() ) - , rTransform( 1 ) - , phiTransform( 0 ) - { - } - - void setTransform( const real_t& rT, const real_t& pT ) - { - rTransform = rT; - phiTransform = pT; - } - real_t getN2() const - { - real_t accN2 = 0; - for ( unsigned int i = 0; i < m_pdf2->size(); ++i ) { - accN2 += std::norm( ( *m_pdf2 )[i].coefficient ) * std::abs( N2.get( i, i ) ); - for ( unsigned int j = i + 1; j < m_pdf2->size(); ++j ) { - accN2 += - 2 * std::real( ( *m_pdf2 )[i].coefficient * std::conj( ( *m_pdf2 )[j].coefficient ) * N2.get( i, j ) ); - } - } - return accN2; - } - - real_t getN1() const - { - real_t accN1 = 0; - for ( unsigned int i = 0; i < m_pdf1->size(); ++i ) { - accN1 += std::norm( ( *m_pdf1 )[i].coefficient ) * std::abs( N1.get( i, i ) ); - for ( unsigned int j = i + 1; j < m_pdf1->size(); ++j ) { - accN1 += - 2 * std::real( ( *m_pdf1 )[i].coefficient * std::conj( ( *m_pdf1 )[j].coefficient ) * N1.get( i, j ) ); - } - } - return accN1 * rTransform * rTransform; - } - - complex_t getVal() - { - complex_t accR( 0, 0 ); - m_pdf1->transferParameters(); - m_pdf2->transferParameters(); - for ( unsigned int i = 0; i < m_pdf1->size(); ++i ) { - for ( unsigned int j = 0; j < m_pdf2->size(); ++j ) { - accR += ( *m_pdf1 )[i].coefficient * std::conj( ( *m_pdf2 )[j].coefficient ) * R.get( i, j ); - } - } - return complex_t( cos( phiTransform ), sin( phiTransform ) ) * rTransform * accR / - sqrt( getN1() * getN2() ); - } - }; - - struct HadronicParameters { - - HadronicParameters( const real_t& _R, const real_t& _d, const real_t& k1 ); - HadronicParameters( const real_t& _R, const real_t& _d, const real_t& k1, const real_t& k2 ); - HadronicParameters() : n1( 0 ), n2( 0 ), wt(0), coherence( 0, 0 ), nFills( 0 ), id( 0 ), binID( 0 ) {} - - real_t n1; - real_t n2; - real_t wt; - complex_t coherence; - unsigned int nFills; - unsigned int id; - unsigned int binID; - real_t I1() const { return n1 / wt ; } - real_t I2() const { return n2 / wt ; } - real_t d() const { return std::arg( coherence ); } - real_t R() const { return std::abs( getCoherence() ); } - real_t r() const { return sqrt( n1 / n2 ); } - complex_t getCoherence() const { return coherence / ( wt * sqrt( I1() * I2() ) ) ; } - void scale_p1( const real_t& sf ); - void scale_p2( const real_t& sf ); - void rotate( const real_t& angle ); - void clear(); - - void add( const complex_t& f1, const complex_t& f2, const real_t& weight = 1 ); - - HadronicParameters operator+=( const HadronicParameters& other ); - HadronicParameters operator-=( const HadronicParameters& other ); - - std::string to_string() const; - }; - - HadronicParameters operator+( const HadronicParameters& a, const HadronicParameters& b ); - class CoherenceFactor - { - private: - HadronicParameters m_global; - real_t m_globalPhase; - real_t m_globalR; - CoherentSum* m_pdf1; - CoherentSum* m_pdf2; - BinDT m_voxels; - std::vector m_paramsPerVoxel; - std::map m_nodeID2Bin; - unsigned int m_nBins; - - CoherenceCalculator m_calc; - EventList* m_data; - EventType m_type; - - void MakeEventDeltaPlots(const std::vector& events ); - public: - BinDT& getDT() { return m_voxels; } - real_t phase(); - real_t getR(); - std::vector getNumberOfEventsInEachBin( const EventList& events ) const; - HadronicParameters calculateGlobalCoherence( EventList* data = nullptr ); - void writeToFile( const std::string& filename ); - - HadronicParameters getVal() const; - CoherenceFactor( const std::string& filename ); - CoherenceFactor(); - CoherenceFactor( CoherentSum* pdf1, CoherentSum* pdf2, EventList* data = nullptr ); - - CoherenceFactor( CoherentSum* pdf1, CoherentSum* pdf2, const EventType& type ); - - void makeCoherentMapping( const unsigned int& nBins, - const std::function( const Event& )>& functors = nullptr, - const size_t& maxDepth = 20, const size_t& minPop = 50, - const std::function& flagFunctor = nullptr, - const bool& refreshEvents = true ); - void makeCoherentMapping( const unsigned int& nBins, const BinDT& binDT ); - - void groupByStrongPhase( const std::vector& coherenceEvents = {}, const bool& recalculateVoxels =true ); - - void readBinsFromFile( const std::string& binName ); /// - unsigned int getBinNumber( const Event& event ) const; - real_t operator()(); - void testCoherenceFactor() const; - - std::vector getCoherenceFactors() const; - std::vector getCoherenceFactorsFast() const; - std::vector coherenceFactorsPerVoxel() const { return m_paramsPerVoxel; } - - void calculateNorms(); - void calculateCoherenceFactorsPerVoxel(); - void calculateCoherenceFactorsPerVoxel( const std::vector& dtEvents ); - - void setGlobals( const real_t& globalPhase, const real_t& globalR ) - { - m_globalR = globalR; - m_globalPhase = globalPhase; - } - void setBinOfNode( const unsigned int& nodeID, const unsigned int& bin ) { m_nodeID2Bin[nodeID] = bin; } - }; -} // namespace AmpGen - -#endif diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index eadb935daf2..3bc13256d47 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -65,7 +65,6 @@ namespace AmpGen void reset( bool resetEvents = false ); void setEvents( EventList& list ); void setMC( EventList& sim ); - void PConjugate(); void debug( const Event& evt, const std::string& nameMustContain=""); void generateSourceCode( const std::string& fname, const double& normalisation = 1, bool add_mt = false ); void resync(); @@ -76,7 +75,6 @@ namespace AmpGen std::map> getGroupedAmplitudes(); Bilinears norms() const { return m_normalisations ; } - protected: std::vector> m_matrixElements; ///< Vector of (expanded) matrix elements diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 377129b5009..67b433039e0 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -24,7 +24,7 @@ namespace AmpGen { - DECLARE_ARGUMENT_DEFAULT( Bins, size_t, 100 ); + DECLARE_ARGUMENT(Bins, size_t); class CompiledExpressionBase; class EventList @@ -165,18 +165,18 @@ namespace AmpGen INFO("Filter removes: " << currentSize - size() << " / " << currentSize << " events"); } }; - DECLARE_ARGUMENT( LineColor, int ); - DECLARE_ARGUMENT( DrawStyle, std::string ); - DECLARE_ARGUMENT( Selection, std::function ); - DECLARE_ARGUMENT( WeightFunction, std::function ); - DECLARE_ARGUMENT( Branches, std::vector ); - DECLARE_ARGUMENT( EntryList, std::vector ); - DECLARE_ARGUMENT_DEFAULT(GetGenPdf, bool, false ); - DECLARE_ARGUMENT_DEFAULT(CacheSize, size_t , 0 ); - DECLARE_ARGUMENT_DEFAULT(Filter, std::string , ""); - DECLARE_ARGUMENT_DEFAULT(WeightBranch, std::string, "" ); - DECLARE_ARGUMENT_DEFAULT(ApplySym, bool, 0 ); - DECLARE_ARGUMENT_DEFAULT(Prefix, std::string, "" ); + DECLARE_ARGUMENT(LineColor, int ); + DECLARE_ARGUMENT(DrawStyle, std::string ); + DECLARE_ARGUMENT(Selection, std::function ); + DECLARE_ARGUMENT(WeightFunction, std::function ); + DECLARE_ARGUMENT(Branches, std::vector ); + DECLARE_ARGUMENT(EntryList, std::vector ); + DECLARE_ARGUMENT(GetGenPdf, bool); + DECLARE_ARGUMENT(CacheSize, size_t); + DECLARE_ARGUMENT(Filter, std::string); + DECLARE_ARGUMENT(WeightBranch, std::string); + DECLARE_ARGUMENT(ApplySym, bool ); + DECLARE_ARGUMENT(Prefix, std::string); } // namespace AmpGen #endif diff --git a/AmpGen/MetaUtils.h b/AmpGen/MetaUtils.h index 31985fe437e..ab9e3fae67c 100644 --- a/AmpGen/MetaUtils.h +++ b/AmpGen/MetaUtils.h @@ -70,7 +70,6 @@ namespace AmpGen { return std::is_constructible::value && (false == std::is_same::value); } - template std::vector typelist() { std::vector< std::string > rt; diff --git a/AmpGen/MinuitParameterSet.h b/AmpGen/MinuitParameterSet.h index b726b9334a3..75b0b736307 100644 --- a/AmpGen/MinuitParameterSet.h +++ b/AmpGen/MinuitParameterSet.h @@ -21,8 +21,9 @@ namespace AmpGen typedef std::vector::const_iterator const_iterator; MinuitParameterSet(); + MinuitParameterSet(const std::vector& params ); MinuitParameterSet( const MinuitParameterSet& other ); - ~MinuitParameterSet(); + ~MinuitParameterSet() = default; MinuitParameterSet getFloating(); @@ -34,24 +35,19 @@ namespace AmpGen void loadFromStream(); void loadFromFile( const std::string& name ); void resetToInit(); + void print( std::ostream& os = std::cout ) const; + void printVariable( std::ostream& os = std::cout ) const; + void set( const MinuitParameterSet& mps ); + void rename(const std::string& name, const std::string& new_name); unsigned int size() const; - std::map& map(); - const std::map& const_map() const; const_iterator cbegin() const; const_iterator cend() const; iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; - - void deleteListAndObjects(); - void deleteListKeepObjects(); - - void print( std::ostream& os = std::cout ) const; - void printVariable( std::ostream& os = std::cout ) const; - - void set( const MinuitParameterSet& mps ); + MinuitParameter* at( const std::string& key ); MinuitParameter* at( const size_t& index ) const; MinuitParameter* operator[]( const std::string& key ); @@ -67,9 +63,7 @@ namespace AmpGen std::vector m_parameters; std::vector m_expressions; std::map m_keyAccess; - }; - } // namespace AmpGen #endif // diff --git a/AmpGen/Particle.h b/AmpGen/Particle.h index 42af4908a84..44a6bb892eb 100644 --- a/AmpGen/Particle.h +++ b/AmpGen/Particle.h @@ -95,32 +95,6 @@ namespace AmpGen class ParticleProperties; class Particle { - private: - const ParticleProperties* m_props; ///< Particle Properties from the PDG - std::string m_name = {""}; ///< Name of the particle - std::string m_lineshape = {"BW"}; ///< Propagator to use - std::string m_uniqueString = {""}; ///< Unique string of particle tree - int m_parity = {0}; ///< Intrinsic parity of particle - int m_polState = {0}; ///< polarisation state - unsigned int m_index = {999}; ///< Index, for constructing four-momenta - unsigned int m_originalIndex = {999}; ///< Starting index, used in Bose-symmetrisation - unsigned int m_orbital = {0}; ///< Orbital angular momentum between daughters - unsigned int m_spinConfigurationNumber = {0}; ///< Spin configuration quantum number 'S' - unsigned int m_minL = {0}; ///< Minimum orbital angular momentum - bool m_isHead = {true}; ///< Flag that particle is head of decay chain - bool m_usesDefaultLineshape = {false}; ///< Flag to check if default shape is used - bool m_isStateGood = {true}; ///< Flag to check the decay is well-formed - std::vector> m_daughters; ///< Array of daughter particles - std::vector m_modifiers; ///< Additional modifiers for amplitude - std::string m_spinFormalism = {""}; ///< Spin formalism to use for this particle (global) - std::string m_spinBasis = {""}; ///< Basis to use for external polarisations (global) - std::string m_defaultModifier = {""}; ///< Default Modifier to use (global) - - void pdgLookup(); ///< Lookup information from the PDG database (using ParticlePropertiesList) - bool hasModifier( const std::string& modifier ) const; ///< Check if this particle has a given modifier - std::string modifierString() const; ///< Re-generate modifier string used to create particle - std::string makeUniqueString(); ///< Generate the decay descriptor for this decay. - void sortDaughters(); ///< Recursively order the particle's decay products. public: /// @constructor default constructor Particle(); @@ -139,10 +113,17 @@ namespace AmpGen /// @function (Quasi) Constructor that returns the (quasi)CP conjugated amplitude. The full behaviour of the amplitude is made more complicated by the ordering convention. Particle conj(bool invertHead = true, bool reorder = true); - + + /// @function Set the orbital quantum number 'L' for this decay. void setOrbital( const unsigned int& orbital ); + + /// @function Set the lineshape for the decay of this particle. void setLineshape( const std::string& lineshape ); + + /// @function Set the index'th daughter of this to particle. void setDaughter( const Particle& particle, const unsigned int& index ); + + /// @function Set the flag to say this void setTop( bool state = true ); void setIndex( const unsigned int& index, const bool& setOri = false ); void clearDecayProducts(); @@ -270,6 +251,33 @@ namespace AmpGen }; /// @function matches Check the matching between two decay chains, according to the MatchState enum. unsigned int matches( const Particle& other ) const; + + private: + const ParticleProperties* m_props; ///< Particle Properties from the PDG + std::string m_name = {""}; ///< Name of the particle + std::string m_lineshape = {"BW"}; ///< Propagator to use + std::string m_uniqueString = {""}; ///< Unique string of particle tree + int m_parity = {0}; ///< Intrinsic parity of particle + int m_polState = {0}; ///< polarisation state + unsigned int m_index = {999}; ///< Index, for constructing four-momenta + unsigned int m_originalIndex = {999}; ///< Starting index, used in Bose-symmetrisation + unsigned int m_orbital = {0}; ///< Orbital angular momentum between daughters + unsigned int m_spinConfigurationNumber = {0}; ///< Spin configuration quantum number 'S' + unsigned int m_minL = {0}; ///< Minimum orbital angular momentum + bool m_isHead = {true}; ///< Flag that particle is head of decay chain + bool m_usesDefaultLineshape = {false}; ///< Flag to check if default shape is used + bool m_isStateGood = {true}; ///< Flag to check the decay is well-formed + std::vector> m_daughters; ///< Array of daughter particles + std::vector m_modifiers; ///< Additional modifiers for amplitude + std::string m_spinFormalism = {""}; ///< Spin formalism to use for this particle (global) + std::string m_spinBasis = {""}; ///< Basis to use for external polarisations (global) + std::string m_defaultModifier = {""}; ///< Default Modifier to use (global) + + void pdgLookup(); ///< Lookup information from the PDG database (using ParticlePropertiesList) + bool hasModifier( const std::string& modifier ) const; ///< Check if this particle has a given modifier + std::string modifierString() const; ///< Re-generate modifier string used to create particle + std::string makeUniqueString(); ///< Generate the decay descriptor for this decay. + void sortDaughters(); ///< Recursively order the particle's decay products. }; std::ostream& operator<<( std::ostream& os, const Particle& particle ); } // namespace AmpGen diff --git a/AmpGen/Plots.h b/AmpGen/Plots.h index 15c5842d643..3994d21ff9c 100644 --- a/AmpGen/Plots.h +++ b/AmpGen/Plots.h @@ -10,9 +10,10 @@ #include "AmpGen/Utilities.h" #include "AmpGen/EventList.h" -#include "TFile.h" -#include "TH1D.h" -#include "TH2D.h" +#include +#include +#include +#include #include namespace AmpGen @@ -97,6 +98,9 @@ namespace AmpGen } return plots; } + TGraph* boundary(const AmpGen::EventType& type, + const std::function& p1, + const std::function& p2 ); } // namespace AmpGen #endif diff --git a/AmpGen/Tensor.h b/AmpGen/Tensor.h index 45d88b8a8e9..b7f4e2dffba 100644 --- a/AmpGen/Tensor.h +++ b/AmpGen/Tensor.h @@ -120,9 +120,8 @@ namespace AmpGen void print(const bool& eval = false) const; - const std::vector& uniqueElements() const { - return m_uniqueElements; - } + const std::vector& uniqueElements() const { return m_uniqueElements; } + void operator+=( const Tensor& rhs ); void operator-=( const Tensor& rhs ); Tensor conjugate() const; diff --git a/CMakeLists.txt b/CMakeLists.txt index 63017dab540..8cf6ef67852 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ # Support standalone build if(COMMAND gaudi_subdir) - gaudi_subdir(AmpGen v1r1) + gaudi_subdir(AmpGen v1r2) find_package(ROOT COMPONENTS RIO Hist Matrix Graf Minuit2 Tree MathMore MathCore Physics) find_package(TBB REQUIRED) @@ -29,6 +29,6 @@ if(COMMAND gaudi_subdir) endforeach() else() cmake_minimum_required(VERSION 3.3) - project(AmpGen LANGUAGES CXX VERSION 1.1) + project(AmpGen LANGUAGES CXX VERSION 1.2) include(Standalone.cmake) endif() diff --git a/apps/Debugger.cpp b/apps/Debugger.cpp index 0c2877497a3..4eb41281d5a 100644 --- a/apps/Debugger.cpp +++ b/apps/Debugger.cpp @@ -70,11 +70,7 @@ void invert( MinuitParameter* param, MinuitParameterSet& mps ) if( props != 0 ) new_name = props->anti().name() + "_" + tokens[1]; } } - if( param->name() != new_name && mps.find(new_name) == nullptr ){ - mps.map().erase( param->name() ); - param->setName( new_name ); - mps.map().emplace( param->name(), param ); - } + mps.rename( param->name(), new_name ); if( sgn == -1 ) param->setCurrentFitVal( -1 * param->mean() ); } diff --git a/apps/Fitter.cpp b/apps/Fitter.cpp index 4a264c5f77a..a9c839a4f32 100644 --- a/apps/Fitter.cpp +++ b/apps/Fitter.cpp @@ -10,7 +10,6 @@ #include #include "AmpGen/Chi2Estimator.h" -#include "AmpGen/CoherenceFactor.h" #include "AmpGen/ErrorPropagator.h" #include "AmpGen/EventList.h" #include "AmpGen/EventType.h" @@ -109,11 +108,10 @@ FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& std::vector slowParamPtrs; if ( nIterations != 0 ) { for ( auto& param : SlowParams ) { - auto mps_map = MPS.map(); - auto it = mps_map.find( param ); - if ( it != mps_map.end() ) { - slowParamPtrs.push_back( it->second ); - it->second->fix(); + auto it = MPS.find( param ); + if ( it != nullptr ) { + slowParamPtrs.push_back( it ); + it->fix(); } else { WARNING( "Trying to release non-existent parameter: " << param ); } diff --git a/doc/doxyfile b/doc/doxyfile index 3d918f6044f..c4db3d1ac5e 100644 --- a/doc/doxyfile +++ b/doc/doxyfile @@ -1247,7 +1247,7 @@ MAN_LINKS = NO # captures the structure of the code including all documentation. # The default value is: NO. -GENERATE_XML = NO +GENERATE_XML = YES # The XML_OUTPUT tag is used to specify where the XML pages will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of diff --git a/doc/release.notes b/doc/release.notes index 9ef40f10271..3c967441082 100644 --- a/doc/release.notes +++ b/doc/release.notes @@ -3,6 +3,7 @@ ! Responsible : Tim Evans ! Purpose : !----------------------------------------------------------------------------- +!=================== AmpGen v1r2 2019-05-17 ================== - Improved thread support for CoherentSum - Add examples/QcGenerator for Ψ(3770) decays !=================== AmpGen v1r1 2019-03-22 ================== @@ -21,8 +22,6 @@ !============================================================= ! 2016-09-06 - Tim Evans - First import of source, apps, headers - - ! 2016-09-02 - Tim Evans - Empty structure for the package !============================================================= diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp index 108ab615b26..058c249a3ae 100644 --- a/examples/QcGenerator.cpp +++ b/examples/QcGenerator.cpp @@ -281,7 +281,7 @@ void add_CP_conjugate( MinuitParameterSet& mps ) if( props != 0 ) new_name = props->anti().name() + "_" + tokens[1]; } } - if( mps.map().count( new_name ) == 0 ){ + if( mps.find( new_name ) == nullptr ){ tmp.push_back( new MinuitParameter(new_name, MinuitParameter::Flag::Float, sgn * param->mean(), param->err(), 0, 0)); } } diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index 3b2f5db229c..bba12f03a35 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "AmpGen/MinuitParameter.h" #include "AmpGen/MinuitParameterSet.h" @@ -14,57 +15,37 @@ #include "AmpGen/NamedParameter.h" using namespace AmpGen; +using namespace std::complex_literals; -AmplitudeRule::AmplitudeRule( const std::string& reName, - const std::map& mapping ) +AmplitudeRule::AmplitudeRule(MinuitParameter* re, MinuitParameter* im ) : + m_re(re), + m_im(im) { - auto tokens = split( reName, '_' ); + auto tokens = split( re->name(), '_' ); if ( tokens.size() == 3 ) { m_prefix = tokens[0]; m_name = tokens[1]; - auto ire = mapping.find( reName ); - auto iim = mapping.find( tokens[0] + "_" + tokens[1] + "_Im" ); - if ( iim == mapping.end() ) { - ERROR( "Well-formed coupling not identified for:" << reName ); - return; - } - m_re = ire->second; - m_im = iim->second; - m_isGood = true; - } else if ( tokens.size() == 2 ) { - m_prefix = ""; m_name = tokens[0]; - auto ire = mapping.find( reName ); - auto iim = mapping.find( tokens[0] + "_Im" ); - if ( iim == mapping.end() ) { - ERROR( "Well-formed coupling not identified for:" << reName ); - return; - } - m_re = ire->second; - m_im = iim->second; - m_isGood = true; - } else { - ERROR( "Too many tokens! " ); - m_isGood = false; } - if ( m_isGood ) { - size_t pos = find_next_of( m_name, {"[", "{"} ); - if ( pos == std::string::npos ) - { - ERROR( "Does not seem to be well formed decay descriptor [" << reName << "]" ); - m_isGood = false; - } + else { + ERROR("Ill-formed decay descriptor: " << m_name ); } m_particle = Particle(m_name); } + AmplitudeRules::AmplitudeRules( const MinuitParameterSet& mps ) { - for ( auto& o : mps.const_map() ) { - if ( o.first.find( "_Re" ) == std::string::npos ) continue; - AmplitudeRule pAmp( o.first, mps.const_map() ); - if ( pAmp.m_isGood ) m_rules[pAmp.m_particle.name()].push_back( pAmp ); + for ( auto& it_re : mps ) { + if ( it_re->name().find("_Re") == std::string::npos ) continue; + auto it_im = mps.find(replaceAll( it_re->name(), "_Re","_Im") ); + if( it_im == nullptr ){ + ERROR("Cannot find matching imaginary part / phase for: " << it_re->name() ); + continue; + } + auto p = AmplitudeRule(it_re, it_im ); + m_rules[p.head()].emplace_back(p); } } @@ -100,17 +81,16 @@ std::map> AmplitudeRules::rules() EventType AmplitudeRule::eventType() const { Particle particle( m_name ); - std::vector particleNames; - particleNames.push_back( particle.name() ); + std::vector particleNames = { particle.name() }; std::vector> fs = particle.getFinalStateParticles(); std::stable_sort( fs.begin(), fs.end(), []( auto& A, auto& B ) { return *A < *B; } ); - for( auto& f : fs ) particleNames.push_back( f->name() ); + std::transform( fs.begin(), fs.end(), std::back_inserter(particleNames), [](auto& p ) -> std::string { return p->name() ; } ); return EventType( particleNames ); } CouplingConstant::CouplingConstant(const AmplitudeRule& pA) { - couplings.emplace_back( std::make_pair(pA.m_re,pA.m_im) ); + couplings.emplace_back(pA.m_re,pA.m_im); std::string cartOrPolar = NamedParameter("CouplingConstant::Coordinates" ,"cartesian"); std::string degOrRad = NamedParameter("CouplingConstant::AngularUnits","rad"); if( cartOrPolar == "polar" ){ @@ -127,31 +107,23 @@ CouplingConstant::CouplingConstant(const AmplitudeRule& pA) std::complex CouplingConstant::operator()() const { - std::complex F( 1, 0 ); - if ( isCartesian ) - for( auto& p : couplings ) F *= complex_t( p.first->mean() , p.second->mean() ); - else - for( auto& p : couplings ) F *= p.first->mean() * complex_t( cos( sf * p.second->mean() ), sin( sf * p.second->mean() ) ); - return F; + return isCartesian ? + std::accumulate( couplings.begin(), couplings.end(), complex_t(1,0), + [this](auto& prod, auto& coupling){ return prod * complex_t( coupling.first->mean(), coupling.second->mean() ) ; } ) + : std::accumulate( couplings.begin(), couplings.end(), complex_t(1,0), + [this](auto& prod, auto& coupling){ return prod * coupling.first->mean() * exp( 1i* this->sf * coupling.second->mean() ) ; } ); } Expression CouplingConstant::to_expression() const { - Expression J = Constant(0,1); if ( isCartesian ) { - Expression total = 1; - for ( auto& p : couplings ) { - total = total * ( Parameter( p.first->name() ) + J * Parameter( p.second->name() ) ); - } - return total; + return std::accumulate( couplings.begin(), couplings.end(), Expression(1), + [](auto& prod, auto& p){ return prod * ( Parameter(p.first->name()) + 1i*Parameter(p.second->name() ) ) ; } ); } else { - Expression angle = 0; - Expression amp = 1; - for ( auto& p : couplings ) { - angle = angle + Parameter( p.second->name() ); - amp = amp * Parameter( p.first->name() ); - } - return amp * ( Cos( sf * angle ) + J * Sin( sf * angle ) ); + auto it = std::accumulate( couplings.begin(), couplings.end(), std::pair(1,0), + [](auto& prod, auto& p) -> std::pair { + return std::make_pair( prod.first * Parameter( p.first->name() ), prod.second + Parameter( p.second->name() ) ); } ); + return it.first * fcn::exp( 1i*sf*it.second ); } } @@ -161,7 +133,9 @@ void CouplingConstant::print() const if ( isCartesian ) for ( auto& coupling : couplings ) INFO( coupling.first->name() + " i " + coupling.second->name() ); else - for ( auto& coupling : couplings ) INFO( coupling.first->name() << " x exp(i" << coupling.second->name() ); + for ( auto& coupling : couplings ) + INFO( coupling.first->name() << " x exp(i" << coupling.second->name() << ") = " << + coupling.first->mean() * exp( 1i * coupling.second->mean() * M_PI / 180. ) ); } std::vector> AmplitudeRules::getMatchingRules(const EventType& type, const std::string& prefix ) @@ -210,21 +184,13 @@ std::vector> AmplitudeRules::getMatchingRu bool CouplingConstant::isFixed() const { - for( auto& c : couplings ) - if( c.first->iFixInit() == 0 or c.second->iFixInit() == 0 ) return false; - return true; + return ! std::any_of( couplings.begin(), couplings.end(), + [](auto& c){ return c.first->iFixInit() == 0 or c.second->iFixInit() == 0 ; } ); } bool CouplingConstant::contains( const std::string& label ) const { - for ( auto& reAndIm : couplings ) - if ( reAndIm.first->name().find( label ) != std::string::npos ) return true; - return false; -} - -void CouplingConstant::changeSign() -{ - auto& top_coupling = *couplings.begin(); - if( isCartesian ) top_coupling.first->setCurrentFitVal( top_coupling.first->mean() * -1. ); + return std::any_of( couplings.begin(), couplings.end(), + [&label](auto& c){ return c.first->name().find(label) != std::string::npos ; } ); } diff --git a/src/BinDT.cpp b/src/BinDT.cpp index b1b13adf8a3..992c7ef482a 100644 --- a/src/BinDT.cpp +++ b/src/BinDT.cpp @@ -69,25 +69,6 @@ unsigned int BinDT::getBinNumber( const double* evt ) const { return ( *m_top )( unsigned int BinDT::size() const { return m_endNodes.size(); } -namespace AmpGen -{ - struct PackedDecision { - uint8_t header; // = 2 bytes - uint8_t index; // = 8 bytes - uint32_t address; // = 2 + 4 bytes - uint32_t left; // = 18 - uint32_t right; // = 24 bytes - double cutVal; // = 14 bytes - }; - struct PackedNode { - uint8_t header; - uint8_t packingBit[1]; - uint32_t address; - uint32_t binNumber; - uint32_t voxNumber; - uint16_t packingBits[3]; - }; -} // namespace AmpGen std::function( const Event& )> BinDT::makeDefaultFunctors() { if ( m_dim == 5 ) { @@ -109,16 +90,10 @@ BinDT::BinDT( const ArgumentPack& args ) m_maxDepth = args.getArg( 999 ); m_dim = args.getArg( 5 ); m_functors = args.getArg( makeDefaultFunctors() ).val; - std::ifstream* stream = args.getArg().val; auto fname = args.getArg(); - if ( stream != nullptr && stream->is_open() ) { - readFromBinary( *stream ); - } else if ( fname.name != "" ) { + if ( fname.name != "" ) { std::ifstream stream( fname.name, fname.mode | std::ios::in ); - if ( fname.mode & std::ios::binary ) - readFromBinary( stream ); - else - readFromStream( stream ); + readFromStream( stream ); } } @@ -159,79 +134,6 @@ void BinDT::readFromStream( std::istream& stream ) } } -void BinDT::readFromBinary( std::ifstream& stream ) -{ - std::map> nodes; - std::map> fti; - char buffer[PACKET_SIZE]; // 24 byte word for the nodes // - size_t edc = 0; - while ( stream.read( buffer, PACKET_SIZE ) ) { - if ( ( uint8_t( buffer[0] ) ) == 0xAA ) { - PackedDecision pd; - memcpy( &pd, buffer, PACKET_SIZE ); - nodes.emplace( pd.address, std::make_shared( pd.index, pd.cutVal ) ); - DEBUG( "header = " << std::hex << (uint8_t)pd.header << std::dec << " index = " << pd.index - << " cut-val = " << pd.cutVal << " left-node = " << pd.left << " right-node=" << std::hex - << pd.right << " " << std::dec << sizeof( PackedDecision ) << " " << PACKET_SIZE ); - fti[pd.address] = std::make_pair( pd.left, pd.right ); - } else if ( uint8_t( buffer[0] ) == 0xBB ) { - edc++; - PackedNode pd; - memcpy( &pd, buffer, PACKET_SIZE ); - nodes.emplace( pd.address, std::make_shared( pd.voxNumber, pd.binNumber ) ); - } else { - ERROR( "Packet header: " << std::hex << uint8_t( buffer[0] ) << " not recognised" ); - } - if ( nodes.size() == 1 ) m_top = nodes.begin()->second; - } - INFO( "Read: " << nodes.size() << " nodes from binary file, now re-establishing tree structure; EndNodes=" << edc ); - - for ( auto& node : nodes ) { - Decision* node_ptr = dynamic_cast( node.second.get() ); - if ( node_ptr == nullptr ) continue; - auto child_nodes = fti.find( node.first ); - if ( child_nodes == fti.end() ) { - ERROR( "Child nodes not found!" ); - } - auto pL = nodes.find( child_nodes->second.first ); - auto pR = nodes.find( child_nodes->second.second ); - if ( pL == nodes.end() || pR == nodes.end() ) { - ERROR( "Nodes for " << node_ptr << " not found! success counter " - << " " << child_nodes->second.first << " " << child_nodes->second.second ); - } else { - node_ptr->setChildren( pL->second, pR->second ); - } - } -} - -void BinDT::writeToBinary( std::ofstream& stream ) -{ - AddressCompressor counter; - m_top->visit( [&stream, &counter]( const INode* node ) { - std::array word; - const BinDT::Decision* decision = dynamic_cast( node ); - if ( decision != nullptr ) { - PackedDecision pd; - pd.header = 0xAA; - pd.address = counter[decision]; // uint32_t ( 0xFFFFFFFF & (uint64_t)this ); - pd.index = decision->m_index; - pd.cutVal = decision->m_value; - pd.left = counter[decision->m_left.get()]; // (uint32_t)m_left.get(); - pd.right = counter[decision->m_right.get()]; // (uint32_t)m_right.get(); - memcpy( word.data(), &pd, PACKET_SIZE ); - } else if ( dynamic_cast( node ) != nullptr ) { - const BinDT::EndNode* endNode = dynamic_cast( node ); - PackedNode pd; - pd.header = 0xBB; - pd.address = counter[endNode]; - pd.binNumber = endNode->m_binNumber; - pd.voxNumber = endNode->m_voxNumber; - memcpy( word.data(), &pd, PACKET_SIZE ); - } - stream.write( (char*)( &word ), sizeof( word ) ); - } ); -} - void BinDT::serialize( std::ofstream& output ) { output << std::setprecision( 17 ); diff --git a/src/CoherenceFactor.cpp b/src/CoherenceFactor.cpp deleted file mode 100644 index 1e1eb6be5c3..00000000000 --- a/src/CoherenceFactor.cpp +++ /dev/null @@ -1,525 +0,0 @@ -#include "AmpGen/CoherenceFactor.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "AmpGen/ArgumentPack.h" -#include "AmpGen/DynamicContainer.h" -#include "AmpGen/Generator.h" -#include "AmpGen/Integrator.h" -#include "AmpGen/MsgService.h" -#include "AmpGen/PhaseSpace.h" -#include "AmpGen/NamedParameter.h" -#include "AmpGen/CompiledExpression.h" -#include "AmpGen/Event.h" -#include "AmpGen/Utilities.h" -#include "TH1.h" - -using namespace AmpGen; - -void HadronicParameters::scale_p1( const real_t& sf ) -{ - n1 /= sf; - coherence /= sqrt( sf ); -} -void HadronicParameters::scale_p2( const real_t& sf ) -{ - n2 /= sf; - coherence /= sqrt( sf ); -} - -void HadronicParameters::rotate( const real_t& angle ) -{ - coherence *= complex_t( cos( angle ), sin( angle ) ); -} - -void HadronicParameters::clear() -{ - n1 = 0; - n2 = 0; - nFills = 0; - id = 0; - wt = 0; - coherence = complex_t( 0, 0 ); -} - -void HadronicParameters::add( const complex_t& f1, - const complex_t& f2, - const real_t& weight ) -{ - n1 += weight * std::norm( f1 ); - n2 += weight * std::norm( f2 ); - wt += weight; - coherence += weight * std::conj(f1) * f2 ; - nFills++; -} - -HadronicParameters::HadronicParameters( const real_t& _R, const real_t& _d, const real_t& k1 ) : - n1(k1*k1), - n2(1), - wt(1), - coherence(k1*_R*cos( M_PI*_d/180.), k1*_R*sin(M_PI*_d/180.)) {} - -HadronicParameters::HadronicParameters( const real_t& _R, const real_t& _d, const real_t& k1, const real_t& k2 ) - : n1( k1 ), - n2( k2 ), - wt(1), - coherence( sqrt( k1 * k2 ) * _R * cos( _d ), sqrt( k1 * k2 ) * _R * sin( _d ) ) {} - -HadronicParameters HadronicParameters::operator+=( const HadronicParameters& other ) -{ - n1 += other.n1; - n2 += other.n2; - coherence += other.coherence; - nFills += other.nFills; - wt += other.wt; - return *this; -} - -HadronicParameters HadronicParameters::operator-=( const HadronicParameters& other ) -{ - n1 -= other.n1; - n2 -= other.n2; - coherence -= other.coherence; - nFills -= other.nFills; - wt -= other.wt; - return *this; -} -HadronicParameters AmpGen::operator+( const HadronicParameters& a, const HadronicParameters& b ) -{ - HadronicParameters hp; - hp.wt = a.wt + b.wt; - hp.n1 = a.n1 + b.n1 ; - hp.n2 = a.n2 + b.n2 ; - hp.coherence = a.coherence + b.coherence ; - hp.nFills = a.nFills + b.nFills; - return hp; -} - -std::string HadronicParameters::to_string() const -{ - auto c = getCoherence(); - std::string total = "R = " + round( R() , 3 ) + " δ = " + round( 180 * d() / M_PI, 2 ) + - " r = " + round( r(), 4 ) + " K = " + round( I1() , 6 ) + " K' = " + round( I2(), 6 ) + " N = " + - std::to_string( wt ) + " ci = " + std::to_string( std::real( c ) ) + " si = " + - std::to_string( std::imag( c ) ) ; - return total; -} - -void CoherenceFactor::makeCoherentMapping( const unsigned int& nBins, - const std::function( const Event& )>& functors, - const size_t& maxDepth, - const size_t& minPop, - const std::function& flagFunctor, - const bool& refreshEvents ) -{ - m_nBins = nBins; - - if ( m_data != nullptr ) { - m_voxels = BinDT( *m_data, Functor( functors ), MinEvents( minPop ) ); - return; - } - if( !refreshEvents ){ - groupByStrongPhase({},false); - return; - } - - size_t population = pow( 2, maxDepth ) * 1.2 * minPop; /// 20 % safety factor /// - Generator<> phsp( m_type ); - phsp.setRandom( new TRandom3() ); - size_t counter = 0; - int otherCounter = 0; - size_t blockSize = 1 * pow( 10, 5 ); - auto makeEvents = [&]( EventList& eventList ) { - bool useFlatEvents = NamedParameter ("CoherenceFactor::FlatEvents",true); - if( useFlatEvents ) phsp.fillEventListPhaseSpace( eventList, blockSize, 0); - else phsp.fillEventList( *m_pdf2, eventList, blockSize ); - - eventList.resetCache(); - - m_pdf1->reset( true ); - m_pdf2->reset( true ); - m_pdf1->setEvents( eventList ); - m_pdf2->setEvents( eventList ); - m_pdf1->prepare(); - m_pdf2->prepare(); - counter += blockSize; - INFO( "Generated: " << counter << " DT events (out of " << population - << " requested); [evt counter=" << otherCounter << "]" ); - }; - DynamicContainer dlist( population, makeEvents ); - std::vector DTevents( population ); - std::vector addresses; - std::vector addresses_veto; - for ( auto evt : dlist ) { - auto& te = DTevents[otherCounter++]; - te.weight = 1./evt.genPdf(); - te.amp1 = m_pdf1->getVal( evt ); - te.amp2 = m_pdf2->getVal( evt ); - auto coords = functors( evt ); - for ( unsigned int i = 0; i < 5; ++i ) - te.values[i] = coords[i]; - if ( flagFunctor != nullptr && flagFunctor( evt ) ) { - te.flag = true; - addresses_veto.push_back( te.values.data() ); - } else { - addresses.push_back( te.values.data() ); - } - } - m_voxels = BinDT( addresses, Functor( functors ), MaxDepth( maxDepth ), MinEvents( minPop ) ); - - INFO( "Generated " << dlist.size() - << " events; entries per node = " << real_t( dlist.size() ) / real_t( m_voxels.nodes().size() ) ); - groupByStrongPhase( DTevents , true ); -} - -void CoherenceFactor::makeCoherentMapping( const unsigned int& nBins, const BinDT& binDT ) -{ - m_voxels = binDT; - m_nBins = nBins; - groupByStrongPhase(); -} - -void CoherenceFactor::calculateCoherenceFactorsPerVoxel() -{ - m_paramsPerVoxel.clear(); - m_paramsPerVoxel.resize( m_voxels.size() + 1 ); - for ( unsigned int i = 0; i < m_paramsPerVoxel.size(); ++i ) m_paramsPerVoxel[i].id = i; - auto pdf1CacheMap = m_pdf1->cacheAddresses( *m_data ); - auto pdf2CacheMap = m_pdf2->cacheAddresses( *m_data ); - - TH1D* deltaPhaseWeightPdf1 = new TH1D( "deltaPhi1","",100,-180,180); - TH1D* deltaPhaseWeightPdf2 = new TH1D( "deltaPhi2","",100,-180,180); - TH1D* deltaPhaseNoWeight = new TH1D( "deltaPhase0","",100,-180,180); - for ( auto& evt : *m_data ) { - int binNumber = m_voxels.getBinNumber( evt ); - real_t w = evt.weight() / evt.genPdf(); - complex_t p1 = m_pdf1->getVal( evt, pdf1CacheMap ); - complex_t p2 = m_pdf2->getVal( evt, pdf2CacheMap ); - real_t arg = std::arg( p1* std::conj(p2 ) ); - deltaPhaseWeightPdf1->Fill( arg * 180 / M_PI, std::abs(p1) ); - deltaPhaseWeightPdf2->Fill( arg * 180 / M_PI, std::abs(p2) ); - deltaPhaseNoWeight->Fill( arg * 180 / M_PI, 1 ); - m_paramsPerVoxel[binNumber].add( p1, p2, w ); - } - deltaPhaseWeightPdf1->Write(); - deltaPhaseWeightPdf2->Write(); - deltaPhaseNoWeight->Write(); -} - -void CoherenceFactor::calculateCoherenceFactorsPerVoxel( const std::vector& dtEvents ) -{ - m_paramsPerVoxel.clear(); - m_paramsPerVoxel.resize( m_voxels.size() + 1 ); - INFO( "h-Voxels = " << m_voxels.size() << " associating with ids" ); - for ( unsigned int i = 0; i < m_paramsPerVoxel.size(); ++i ) m_paramsPerVoxel[i].id = i; - - TH1D* deltaPhaseNoWeight = new TH1D( "deltaPhi0","",100,-180,180); - TH1D* deltaPhaseWeightVN = new TH1D( "deltaVPhiN","",100,-180,180); - TH1D* weight = new TH1D("weight","",100,0,100); - - HadronicParameters hG; - for ( auto& evt : dtEvents ) { - unsigned int binNumber = evt.flag ? m_voxels.size() : m_voxels.getBinNumber( evt.values.data() ); - DEBUG( "BinNumber: " << binNumber << " pos = {" << evt.values[0] << "," << evt.values[1] << "," << evt.values[2] - << "," << evt.values[3] << "," << evt.values[4] << "}" ); - real_t arg = std::arg( std::conj(evt.amp1) * evt.amp2 ); - deltaPhaseNoWeight->Fill( arg * 180 / M_PI, 1 ); - weight->Fill( evt.weight ); - m_paramsPerVoxel[binNumber].add( evt.amp1, evt.amp2, evt.weight ); - hG.add( evt.amp1, evt.amp2, evt.weight ); - } - INFO( hG.to_string() ); - for( auto& v : m_paramsPerVoxel ) deltaPhaseWeightVN->Fill( v.d()*180/M_PI, 1 ); - deltaPhaseNoWeight->Write(); - deltaPhaseWeightVN->Write(); - weight->Write(); -} - -void CoherenceFactor::groupByStrongPhase( const std::vector& coherenceEvent, const bool& recalculateVoxels ) -{ - if( recalculateVoxels ){ - if ( m_data != nullptr ) - calculateCoherenceFactorsPerVoxel(); - else - calculateCoherenceFactorsPerVoxel( coherenceEvent ); - } - INFO( "Got " << m_voxels.size() << " voxels" ); - HadronicParameters global_hp; - for ( auto& h : m_paramsPerVoxel ) global_hp += h; - - INFO( "Global parameters = " << global_hp.to_string() ); - real_t phiTransform = m_globalPhase - global_hp.d(); - real_t rTransform = m_globalR * m_globalR * global_hp.n2 / global_hp.n1; - - INFO( "Global rotation = " << phiTransform * 180 / M_PI ); - for ( auto& h : m_paramsPerVoxel ) { - h.scale_p1( 1. / rTransform ); - h.rotate( phiTransform ); - } - INFO( "Transform = " << sqrt( rTransform ) << " ; phi = " << phiTransform ); - - HadronicParameters global_hp_new = std::accumulate( m_paramsPerVoxel.begin(), m_paramsPerVoxel.end() - 1, HadronicParameters() ); - INFO( global_hp_new.to_string() ); - std::sort( m_paramsPerVoxel.begin(), m_paramsPerVoxel.end() - 1, []( auto& b1, auto& b2 ) { return b1.d() < b2.d(); } ); - - real_t norm_target = global_hp_new.wt / real_t( m_nBins ); - unsigned int currentBin = 0; - std::vector> binLimits; - binLimits.emplace_back( -M_PI, 0 ); - INFO( "Normalisation-per-bin = " << norm_target << " i1 = " << global_hp_new.I1() ); - auto currentBinLimits = binLimits.rbegin(); - HadronicParameters hp_accumulator, glob_vox_test; - - for( auto ihp = m_paramsPerVoxel.begin(); ihp != m_paramsPerVoxel.end() - 1; ++ihp ) { - ihp->binID = currentBin; - m_nodeID2Bin[ihp->id] = currentBin; - hp_accumulator += *ihp; - if ( hp_accumulator.wt > norm_target ) { - currentBinLimits->second = ihp->d(); - currentBin++; - binLimits.emplace_back( ihp->d(), 0 ); - currentBinLimits = binLimits.rbegin(); - glob_vox_test += hp_accumulator; - hp_accumulator.clear(); - } - } - INFO("Generated: " << currentBin << " bins"); - glob_vox_test += hp_accumulator; - m_paramsPerVoxel.rbegin()->binID = m_nBins; // allocate veto bin /// - // for( auto& bin : m_para - // INFO( "[ " << currentBin + 1 << " ] " << hp_test.to_string() ); - INFO( "[ VETO ] " << m_paramsPerVoxel.rbegin()->to_string() ); - INFO( "[ NO VETO ] " << glob_vox_test.to_string() ); - - glob_vox_test += *m_paramsPerVoxel.rbegin(); - INFO( "[SUM VOXELS] " << global_hp_new.to_string() ); - INFO( "[SUM BINS ] " << glob_vox_test.to_string() ); - if( recalculateVoxels && m_data == nullptr ) MakeEventDeltaPlots( coherenceEvent ); - // for ( auto& limits : binLimits ) { - // INFO( "Bin Limits [" << limits.first << ", " << limits.second << "]" ); - // } -} - -void CoherenceFactor::MakeEventDeltaPlots( const std::vector& events ) { - - std::vector plots; - for(size_t i = 0 ; i < m_nBins ; ++i ) - plots.push_back( new TH1D( ("Bin_"+std::to_string(i)+"_deltaPhi").c_str(),0,100,-180,180) ); - for( auto& event : events ){ - unsigned int voxNumber = event.flag ? m_voxels.size() : m_voxels.getBinNumber( event.values.data() ); - real_t arg = std::arg( std::conj(event.amp1) * event.amp2 ); - auto binNumber = m_nodeID2Bin[ voxNumber ]; - if( ! event.flag ) plots[binNumber]->Fill( arg*180/M_PI ); - } - for( auto& plot : plots ) plot->Write(); -} - - - -void CoherenceFactor::testCoherenceFactor() const -{ - - BinnedIntegrator<8> bid( m_data ); - bid.setView( [this]( auto& evt ) { return this->getBinNumber( evt ); } ); - std::vector calcs( 8, CoherenceCalculator( m_pdf1, m_pdf2 ) ); - - size_t PDF1_size = m_pdf1->size(); - size_t PDF2_size = m_pdf2->size(); - for ( unsigned int i = 0; i < PDF1_size; ++i ) { - for ( unsigned int j = 0; j < PDF2_size; ++j ) { - bid.addIntegral( ( *m_pdf1 )[i].pdf, ( *m_pdf2 )[j].pdf, [i, j, &calcs]( const auto& val ) { - for ( unsigned int bin = 0; bin < 8; ++bin ) calcs[bin].R.set( i, j, val[bin] ); - } ); - } - } - for ( unsigned int i = 0; i < PDF1_size; ++i ) { - for ( unsigned int j = i; j < PDF1_size; ++j ) { - bid.addIntegral( ( *m_pdf1 )[i].pdf, ( *m_pdf1 )[j].pdf, [i, j, &calcs]( const auto& val ) { - for ( unsigned int bin = 0; bin < 8; ++bin ) { - calcs[bin].N1.set( i, j, val[bin] ); - if ( i != j ) calcs[bin].N1.set( j, i, std::conj( val[bin] ) ); - } - } ); - } - } - for ( unsigned int i = 0; i < PDF2_size; ++i ) { - for ( unsigned int j = i; j < PDF2_size; ++j ) { - bid.addIntegral( ( *m_pdf2 )[i].pdf, ( *m_pdf2 )[j].pdf, [i, j, &calcs]( const auto& val ) { - for ( unsigned int bin = 0; bin < 8; ++bin ) { - calcs[bin].N2.set( i, j, val[bin] ); - if ( i != j ) calcs[bin].N2.set( j, i, std::conj( val[bin] ) ); - } - } ); - } - } - bid.flush(); - - for ( unsigned int i = 0; i < 8; ++i ) { - complex_t VALUE = calcs[i].getVal(); - INFO( "Bin [" << i + 1 << "] R=" << std::abs( VALUE ) << " d= " << 180 * std::arg( VALUE ) / M_PI - << " N1= " << calcs[i].getN1() << " N2= " << calcs[i].getN2() ); - } -} - -std::vector CoherenceFactor::getCoherenceFactors() const -{ - std::vector R( m_nBins + 1 ); - HadronicParameters RG; - auto pdf1CacheMap = m_pdf1->cacheAddresses( *m_data ); - auto pdf2CacheMap = m_pdf2->cacheAddresses( *m_data ); - for ( auto& evt : *m_data ) { - unsigned int binNumber = getBinNumber( evt ); - real_t w = evt.weight() / evt.genPdf(); - complex_t p1 = m_pdf1->getVal( evt, pdf1CacheMap ); - complex_t p2 = m_pdf2->getVal( evt, pdf2CacheMap ); - R[binNumber].add( p1, p2, w ); - RG.add( p1, p2, w ); - } - real_t phiTransform = m_globalPhase - std::arg( RG.coherence ); - real_t rTransform = m_globalR * m_globalR * RG.n2 / RG.n1; - for ( auto& h : R ) { - h.scale_p1( 1. / rTransform ); - h.rotate( phiTransform ); - } - INFO( RG.to_string() ); - return R; -} - -std::vector CoherenceFactor::getCoherenceFactorsFast() const -{ - - std::vector coherence_factors( m_nBins + 1 ); - for ( auto hp = m_paramsPerVoxel.begin(); hp != m_paramsPerVoxel.end() - 1; ++hp ) { - coherence_factors[hp->binID] += *hp; - } - coherence_factors[m_nBins] = *m_paramsPerVoxel.rbegin(); - return coherence_factors; -} - -std::vector CoherenceFactor::getNumberOfEventsInEachBin( const EventList& events ) const -{ - - std::vector counter( m_nBins + 1, 0 ); - for ( auto& event : events ) { - counter[getBinNumber( event )]++; - } - return counter; -} - -CoherenceFactor::CoherenceFactor( const std::string& filename ) { readBinsFromFile( filename ); } - -void CoherenceFactor::readBinsFromFile( const std::string& binName ) -{ - INFO( "Reading file = " << binName ); - m_voxels = BinDT( File( binName ) ); - m_nBins = 0; - for ( auto& node : m_voxels.nodes() ) { - m_nodeID2Bin[node->voxNumber()] = node->binNumber(); - if ( node->binNumber() != 999 && node->binNumber() >= m_nBins ) m_nBins = node->binNumber() + 1; - } - INFO( "Got " << m_nBins << " coherent bins and " << m_voxels.size() << " voxels" ); -} - -real_t CoherenceFactor::phase() { return std::arg( m_global.getCoherence() ); } -real_t CoherenceFactor::getR() { return std::abs( m_global.getCoherence() ); } - -HadronicParameters CoherenceFactor::calculateGlobalCoherence( EventList* _data ) -{ - m_global.clear(); - bool freshData = false; - if ( _data == nullptr ) { - _data = new EventList( m_type ); - PhaseSpace phsp( m_type ); - phsp.setRandom( new TRandom3() ); - for ( unsigned int i = 0; i < 1e6; ++i ) _data->push_back( phsp.makeEvent( m_pdf1->size() + m_pdf2->size() ) ); - freshData = true; - } - m_pdf1->setMC( *_data ); - m_pdf2->setMC( *_data ); - m_pdf1->prepare(); - m_pdf2->prepare(); - auto pdf1CacheMap = m_pdf1->cacheAddresses( *_data ); - auto pdf2CacheMap = m_pdf2->cacheAddresses( *_data ); - for ( unsigned int i = 0; i < _data->size(); ++i ) { - const Event& evt = ( *_data )[i]; - real_t w = evt.weight() / evt.genPdf(); - complex_t pdf1 = m_pdf1->getVal( evt, pdf1CacheMap ); - complex_t pdf2 = m_pdf2->getVal( evt, pdf2CacheMap ); - m_global.add( pdf1, pdf2, w ); - } - - if ( freshData ) delete _data; - return m_global; -} - -void CoherenceFactor::writeToFile( const std::string& filename ) -{ - auto endNodes = m_voxels.nodes(); - for ( auto& node : endNodes ) { - node->setBinNumber( m_nodeID2Bin[node->voxNumber()] ); - } - m_voxels.serialize( filename ); -} - -HadronicParameters CoherenceFactor::getVal() const { return m_global; } -CoherenceFactor::CoherenceFactor() = default; - -CoherenceFactor::CoherenceFactor( CoherentSum* pdf1, CoherentSum* pdf2, EventList* data ) - : m_pdf1( pdf1 ), m_pdf2( pdf2 ), m_calc( pdf1, pdf2 ), m_data( data ) -{ - if ( m_data != nullptr ) { - calculateGlobalCoherence( m_data ); - calculateNorms(); - m_type = m_data->eventType(); - } -} - -CoherenceFactor::CoherenceFactor( CoherentSum* pdf1, CoherentSum* pdf2, const EventType& type ) - : m_pdf1( pdf1 ), m_pdf2( pdf2 ), m_calc( pdf1, pdf2 ), m_data( nullptr ), m_type( type ) -{ -} - -void CoherenceFactor::calculateNorms() -{ - Integrator<10> id( m_data ); - for ( unsigned int i = 0; i < m_pdf1->size(); ++i ) { - for ( unsigned int j = 0; j < m_pdf2->size(); ++j ) { - id.addIntegral( ( *m_pdf1 )[i].pdf, ( *m_pdf2 )[j].pdf, - [i, j, this]( const complex_t& val ) { this->m_calc.R.set( i, j, val ); } ); - } - } - - for ( unsigned int i = 0; i < m_pdf1->size(); ++i ) { - for ( unsigned int j = i; j < m_pdf1->size(); ++j ) { - id.addIntegral( ( *m_pdf1 )[i].pdf, ( *m_pdf1 )[j].pdf, [i, j, this]( const complex_t& val ) { - this->m_calc.N1.set( i, j, val ); - if ( i != j ) this->m_calc.N1.set( j, i, std::conj( val ) ); - } ); - } - } - - for ( unsigned int i = 0; i < m_pdf2->size(); ++i ) { - for ( unsigned int j = i; j < m_pdf2->size(); ++j ) { - id.addIntegral( ( *m_pdf2 )[i].pdf, ( *m_pdf2 )[j].pdf, [i, j, this]( const complex_t& val ) { - this->m_calc.N2.set( i, j, val ); - if ( i != j ) this->m_calc.N2.set( j, i, std::conj( val ) ); - } ); - } - } - - id.flush(); -} - -unsigned int CoherenceFactor::getBinNumber( const Event& event ) const -{ - int voxelID = m_voxels.getBinNumber( event ); - return voxelID == -1 ? m_nBins : m_nodeID2Bin.find( voxelID )->second; -} -real_t CoherenceFactor::operator()() { return std::abs( m_calc.getVal() ); } diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index feb3726e9aa..1e509da4798 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -50,7 +50,7 @@ CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, m_matrixElements[i] = TransitionMatrix( amplitudes[i].first, amplitudes[i].second, mps, this->m_evtType.getEventFormat(), this->m_dbThis); CompilerWrapper().compile( m_matrixElements[i].pdf, this->m_objCache); } ); } - m_isConstant = isFixedPDF(mps); + m_isConstant = false ; // isFixedPDF(mps); } void CoherentSum::prepare() @@ -260,13 +260,6 @@ bool CoherentSum::isFixedPDF(const MinuitParameterSet& mps) const return true; } -void CoherentSum::PConjugate() -{ - for ( auto& matrixElement : m_matrixElements ) { - if ( matrixElement.decayTree.finalStateParity() == -1 ) matrixElement.coupling.changeSign(); - } -} - complex_t CoherentSum::getValNoCache( const Event& evt ) const { return std::accumulate( m_matrixElements.begin(), diff --git a/src/EventList.cpp b/src/EventList.cpp index c49807c6a39..3d1daa9c173 100644 --- a/src/EventList.cpp +++ b/src/EventList.cpp @@ -57,12 +57,12 @@ void EventList::loadFromFile( const std::string& fname, const ArgumentPack& args void EventList::loadFromTree( TTree* tree, const ArgumentPack& args ) { ProfileClock read_time; - auto pdfSize = args.getArg().val; - auto filter = args.getArg().val; - auto getGenPdf = args.getArg(true).val; - auto weightBranch = args.getArg().val; + auto pdfSize = args.getArg(0).val; + auto filter = args.getArg(std::string("")).val; + auto getGenPdf = args.getArg(false).val; + auto weightBranch = args.getArg(std::string("")).val; auto branches = args.getArg().val; - auto applySym = args.getArg().val; + auto applySym = args.getArg(false).val; auto entryList = args.getArg().val; auto eventFormat = m_eventType.getEventFormat( true ); @@ -156,7 +156,7 @@ TH1D* EventList::makeProjection( const Projection& projection, const ArgumentPac { auto selection = args.getArg().val; auto weightFunction = args.getArg().val; - std::string prefix = args.getArg(); + std::string prefix = args.getArg(std::string("")); auto plot = projection.plot(prefix); plot->SetLineColor(args.getArg(kBlack).val); plot->SetMarkerSize(0); diff --git a/src/EventType.cpp b/src/EventType.cpp index 9b695d68b1f..03bed2e05a9 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -168,7 +168,7 @@ Projection EventType::projection(const size_t& nBins, const std::vector& bool useRootLabelling = NamedParameter("EventType::UseRootTEX", false ); auto mm = minmax(indices, true); std::string gevcccc = useRootLabelling ? "GeV^{2}/c^{4}" : "\\mathrm{GeV}^{2}/c^{4}"; - std::string gevcc = useRootLabelling ? "GeV/c^{2}" : "\\mathrm{GeV}/c^{2}"; + std::string gevcc = useRootLabelling ? "GeV/c^{2}" : "\\mathrm{GeV}/c^{2}"; if( observable == "mass2" ) return Projection( [indices]( const Event& evt ) { return evt.s( indices ); }, "s" + vectorToString( indices ), diff --git a/src/ExpressionParser.cpp b/src/ExpressionParser.cpp index 5e7850f7bdb..338710c4abb 100644 --- a/src/ExpressionParser.cpp +++ b/src/ExpressionParser.cpp @@ -112,13 +112,10 @@ Expression ExpressionParser::processEndPoint( const std::string& name ) if ( name == "i" ) return Constant( 0, 1 ); if ( m_mps != nullptr ) { - auto map = m_mps->map(); - auto it = map.find( name ); - if ( it != map.end() ) - return MinuitParameterLink( it->second ); + auto it = m_mps->find(name); + if ( it != nullptr ) return MinuitParameterLink( it ); else { - WARNING( "Token not understood: " << name << " [map size = " << map.size() << "]" ); - for ( auto& ip : map ) INFO( "map entry = " << ip.first ); + WARNING( "Token not understood: " << name << " [map size = " << m_mps->size() << "]" ); } } return Parameter( name, 0, true ); diff --git a/src/MinuitParameterSet.cpp b/src/MinuitParameterSet.cpp index 8c1f7ea8cc1..b14964f2f59 100644 --- a/src/MinuitParameterSet.cpp +++ b/src/MinuitParameterSet.cpp @@ -21,10 +21,12 @@ using namespace AmpGen; MinuitParameterSet::MinuitParameterSet() = default; -MinuitParameterSet::MinuitParameterSet( const MinuitParameterSet& other ) - : m_parameters( other.m_parameters ), m_keyAccess( other.m_keyAccess ) +MinuitParameterSet::MinuitParameterSet(const std::vector& params ) { + for( auto& param : params ) add(param); } +MinuitParameterSet::MinuitParameterSet( const MinuitParameterSet& other ) + : m_parameters( other.m_parameters ), m_keyAccess( other.m_keyAccess ){} MinuitParameterSet MinuitParameterSet::getFloating() { @@ -39,9 +41,7 @@ bool MinuitParameterSet::addToEnd( MinuitParameter* parPtr ) { bool success = true; if ( nullptr == parPtr ) return false; - m_parameters.push_back( parPtr ); - if ( m_keyAccess.find( parPtr->name() ) != m_keyAccess.end() ) { WARNING( "Parameter with name " << parPtr->name() << " already exists!" ); } @@ -70,14 +70,6 @@ bool MinuitParameterSet::unregister( MinuitParameter* parPtr ) unsigned int MinuitParameterSet::size() const { return m_parameters.size(); } -void MinuitParameterSet::deleteListAndObjects() -{ - for ( auto it = m_parameters.begin(); it != m_parameters.end(); ++it ) delete *it; - m_parameters.clear(); -} - -void MinuitParameterSet::deleteListKeepObjects() { m_parameters.clear(); } - void MinuitParameterSet::print( std::ostream& os ) const { for (size_t i = 0; i < size(); i++ ) { @@ -229,8 +221,6 @@ void MinuitParameterSet::loadFromFile( const std::string& file ) } ); } -MinuitParameterSet::~MinuitParameterSet() = default; - void MinuitParameterSet::set( const MinuitParameterSet& other ) { for ( auto& param : *this ) { @@ -244,14 +234,29 @@ void MinuitParameterSet::resetToInit() for ( auto& param : *this ) param->resetToInit(); } +void MinuitParameterSet::rename(const std::string& name, const std::string& new_name) +{ + auto it = at(name); + if( it == nullptr ){ + ERROR("Parameter: " << name << " not found"); + return; + } + if( name == new_name ) return; + if( at(new_name) != nullptr ){ + ERROR("New key for " << name << " = " << new_name << " already exists"); + return; + } + it->setName(new_name); + m_keyAccess.erase(name); + m_keyAccess.emplace(new_name, it); +} + MinuitParameter* MinuitParameterSet::addOrGet( const std::string& name, const unsigned int& flag, const double& mean, const double& sigma, const double& min, const double& max ) { if ( m_keyAccess.count( name ) != 0 ) return m_keyAccess[name]; return add( name, flag, mean, sigma, min, max ); } -std::map& MinuitParameterSet::map() { return m_keyAccess; } -const std::map& MinuitParameterSet::const_map() const { return m_keyAccess; } MinuitParameterSet::const_iterator MinuitParameterSet::cbegin() const { return m_parameters.cbegin(); } MinuitParameterSet::const_iterator MinuitParameterSet::cend() const { return m_parameters.cend(); } MinuitParameterSet::iterator MinuitParameterSet::begin() { return m_parameters.begin(); } diff --git a/src/OptionsParser.cpp b/src/OptionsParser.cpp index 62b606c2ff6..08e27e94eb2 100644 --- a/src/OptionsParser.cpp +++ b/src/OptionsParser.cpp @@ -75,31 +75,30 @@ void OptionsParser::import( const std::string& fName ) int braceDepth = 0 ; std::vector currentTokens; processFile( fName, [this, ¤tTokens, &braceDepth]( auto& line ) { - if ( this->ignoreThisLine( line ) ) return; - auto tokens = this->makeParsedStrings( line, braceDepth ); - for ( auto& token : tokens ) currentTokens.push_back( token ); - if ( tokens.size() == 0 ) return; - std::string name = currentTokens[0]; - if ( name == "Import" && currentTokens.size() == 2 ) { + if ( this->ignoreThisLine( line ) ) return; + auto tokens = this->makeParsedStrings( line, braceDepth ); + for ( auto& token : tokens ) currentTokens.push_back( token ); + if ( tokens.size() == 0 ) return; + std::string name = currentTokens[0]; + if ( name == "Import" && currentTokens.size() == 2 ) { this->import( expandGlobals( tokens[1] ) ); currentTokens.clear(); return; - } - if ( name == "Alias" && currentTokens.size() == 3 ) { + } + if ( name == "ParticlePropertiesList::Alias" && currentTokens.size() == 3 ) { ParticlePropertiesList::getMutable()->makeAlias( tokens[1], tokens[2] ); currentTokens.clear(); return; - } - if ( braceDepth == 0 ) { - if ( this->m_parsedLines.find( name ) != this->m_parsedLines.end() ) { + } + if ( braceDepth != 0 ) return; + if ( this->m_parsedLines.find( name ) != this->m_parsedLines.end() ) { WARNING( "Overwriting parameter: " << name ); - } - currentTokens.erase( std::remove_if( currentTokens.begin(), currentTokens.end(), - []( const std::string& o ) { return o == "{" || o == "}"; } ), - currentTokens.end() ); - this->m_parsedLines[name] = currentTokens; - currentTokens.clear(); - } + } + currentTokens.erase( std::remove_if( currentTokens.begin(), currentTokens.end(), + []( const std::string& o ) { return o == "{" || o == "}"; } ), + currentTokens.end() ); + this->m_parsedLines[name] = currentTokens; + currentTokens.clear(); } ); @@ -117,7 +116,6 @@ std::vector OptionsParser::makeParsedStrings( const std::string& li { std::string s = line; if ( s.empty() ) return {}; - s.push_back( ' ' ); // makes sure we get last element s = " " + s; // makes things easier when we start with quotes. std::string::const_iterator prev = s.begin(); diff --git a/src/Particle.cpp b/src/Particle.cpp index 0a29b7d6dd0..020cae11406 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -102,8 +102,7 @@ Particle::Particle( const std::string& decayString, const std::vectorprops()->isFermion() ? -1 : 1 ); for(auto& ordering : orderings){ auto exchangeParity = minSwaps( ordering, exchangeParities ); - //INFO( vectorToString( ordering, ", ") << " " << exchangeParity.second ); setOrdering( ordering ); Expression spinFactor = 1; if( includeSpin && spinFormalism == "Covariant" ){ @@ -694,9 +692,7 @@ bool Particle::conservesParity( unsigned int L ) const std::string Particle::topologicalString() const { - std::string topo = ""; - for ( auto& d : m_daughters ) topo += d->m_props->J(); - return topo; + return std::accumulate( m_daughters.begin(), m_daughters.end(), std::string(""), [](auto& s, auto& d){ return s+d->props()->J() ; } ); } const ParticleProperties* Particle::props() const { return m_props; } bool Particle::isHead() const { return m_isHead; } diff --git a/src/Plots.cpp b/src/Plots.cpp index 9e9f5685a20..3a41d57b369 100644 --- a/src/Plots.cpp +++ b/src/Plots.cpp @@ -9,6 +9,8 @@ #include "AmpGen/Utilities.h" #include "AmpGen/EventList.h" #include "AmpGen/Plots.h" +#include "AmpGen/DalitzIntegrator.h" + #include "TFile.h" #include "TH1D.h" #include "TH2D.h" @@ -69,4 +71,39 @@ void AmpGen::perAmplitudePlot( const EventList& evts, dir->Write(); gFile->cd(); } + +TGraph* AmpGen::boundary(const AmpGen::EventType& eventType, + const std::function& p1, + const std::function& p2 ) +{ + auto s0 = pow(eventType.motherMass(),2); + auto s1 = pow(eventType.mass(0),2); + auto s2 = pow(eventType.mass(1),2); + auto s3 = pow(eventType.mass(2),2); + + DalitzIntegrator di( s0, s1, s2, s3 ); + + TGraph* gboundary = new TGraph(); + + Event tmp(12); + + for( double x = 0 ; x <= 1; x+=0.001){ + di.setEvent( {x,0}, tmp.address() ); + gboundary->SetPoint( gboundary->GetN(), p1(tmp), p2(tmp) ); + } + for( double y = 0 ; y <= 1; y+=0.01){ + di.setEvent( {1,y}, tmp.address() ); + gboundary->SetPoint( gboundary->GetN(), p1(tmp), p2(tmp) ); + } + for( double x = 0 ; x <= 1; x+=0.001){ + di.setEvent( {1-x,1}, tmp.address() ); + gboundary->SetPoint( gboundary->GetN(), p1(tmp), p2(tmp) ); + } + for( double y = 0 ; y <= 1; y+=0.01){ + di.setEvent( {0,1-y}, tmp.address() ); + gboundary->SetPoint( gboundary->GetN(), p1(tmp), p2(tmp) ); + } + return gboundary; +} + #endif diff --git a/src/Simplify.cpp b/src/Simplify.cpp index cb88aedd9a7..aef16347bc4 100644 --- a/src/Simplify.cpp +++ b/src/Simplify.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "AmpGen/MsgService.h" @@ -38,6 +40,7 @@ NormalOrderedExpression::Term::Term( const Expression& expression ) : std::sort( m_terms.begin(), m_terms.end(), [](auto& t1, auto& t2 ){ return t1.second > t2.second; } ) ; + // Expression t = std::accumulate( m_terms.begin(), m_terms.end(), Expression(1), std::multiplies() ); Expression t = 1; for( auto& f : m_terms ) t = t * f.first; m_expressionAsString = ( t / m_divisor).to_string(); diff --git a/src/Tensor.cpp b/src/Tensor.cpp index f54fa7d9434..bc0a712903a 100644 --- a/src/Tensor.cpp +++ b/src/Tensor.cpp @@ -35,19 +35,7 @@ Tensor::Tensor( const std::vector& elements ) setupCoordinates(); for(auto& element : elements) append( element ); } -/* -Tensor::Tensor( const std::vector& elements ) -{ - if( elements.size() == 0 ) return Tensor(); - std::vector rank; - rank.push_back( elements.size() ); - for( auto& d : element[0].dims() ) rank.push_back( d ); - for( int i = 0 ; i < elements.size(); ++i ) - { - - } -} -*/ + Expression Tensor::get( const size_t& co ) { if ( co >= m_elements.size() ) diff --git a/src/ThreeBodyCalculators.cpp b/src/ThreeBodyCalculators.cpp index 2175a82aa8f..66dfe18de13 100644 --- a/src/ThreeBodyCalculators.cpp +++ b/src/ThreeBodyCalculators.cpp @@ -183,9 +183,6 @@ ThreeBodyCalculator::ThreeBodyCalculator( const std::string& head, MinuitParamet finalStates.push_back( type ); } for ( auto& type : finalStates ) m_widths.emplace_back( type, mps ); - - bool isReady = true; - for( auto& width : m_widths ) isReady &= width.totalWidth.isReady(); if( nKnots != 999) setAxis( nKnots, min, max ); } @@ -205,7 +202,7 @@ void ThreeBodyCalculator::updateRunningWidth( MinuitParameterSet& mps, const dou double s = m_min + double(c) * m_step; double I = getWidth(s); const std::string knotName = m_name + "::Spline::Gamma::" + std::to_string( c ); - if ( mps.map().find( knotName ) != mps.map().end() ) mps[knotName]->setCurrentFitVal( I ); + if ( mps.find( knotName ) != nullptr ) mps[knotName]->setCurrentFitVal( I ); INFO( knotName << " = " << I ); } } diff --git a/src/Utilities.cpp b/src/Utilities.cpp index 81c90ee59ab..950747848cd 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -11,7 +11,7 @@ #include #include #include - +#include #include "AmpGen/MsgService.h" std::vector AmpGen::vectorFromFile( const std::string& filename, const char ignoreLinesThatBeginWith ) @@ -42,11 +42,8 @@ std::vector AmpGen::split( const std::string& s, const std::vector< { std::vector elems; std::stringstream ss( s ); - std::string strDelim = ""; + std::string strDelim = std::accumulate( delims.begin(), delims.end(), std::string("") ); std::string line; - - for ( auto& st : delims ) strDelim += st; - while ( std::getline( ss, line ) ) { std::size_t prev = 0, pos; while ( ( pos = line.find_first_of( strDelim, prev ) ) != std::string::npos ) { @@ -145,11 +142,11 @@ std::vector AmpGen::getItems( const std::string& tree, const std::v std::vector daughterTrees; size_t begin_position = matched_braces.begin()->first + 1; for ( auto& comma : commas ) { - auto braces = matched_braces.begin() + 1; - for ( ; braces != matched_braces.end(); ++braces ) { - if ( comma > braces->first && comma < braces->second ) break; + auto itBrace = matched_braces.begin() + 1; + for ( ; itBrace != matched_braces.end(); ++itBrace ) { + if ( comma > itBrace->first && comma < itBrace->second ) break; } - if ( braces == matched_braces.end() ) { + if ( itBrace == matched_braces.end() ) { items.push_back( tree.substr( begin_position, comma - begin_position ) ); begin_position = comma + 1; } @@ -315,7 +312,7 @@ std::string AmpGen::expandGlobals( std::string path ) do { pos = path.find( "$" ); if ( pos == std::string::npos ) break; - size_t end_pos = std::string::npos; + size_t end_pos; // = std::string::npos; std::string variable_name; if ( path[pos + 1] == '{' ) { end_pos = path.find( "}", pos ); diff --git a/src/Vertex.cpp b/src/Vertex.cpp index ceb1b9a27f4..5c1faf158df 100644 --- a/src/Vertex.cpp +++ b/src/Vertex.cpp @@ -12,12 +12,15 @@ #include "AmpGen/Units.h" using namespace AmpGen; -//using namespace AmpGen::Vertex; const Tensor::Index mu = Tensor::Index(); const Tensor::Index nu = Tensor::Index(); const Tensor::Index alpha = Tensor::Index(); const Tensor::Index beta = Tensor::Index(); +const Tensor::Index a = Tensor::Index(); +const Tensor::Index b = Tensor::Index(); +const Tensor::Index c = Tensor::Index(); +const Tensor::Index d = Tensor::Index(); template <> Factory* Factory::gImpl = nullptr; @@ -63,8 +66,6 @@ Tensor AmpGen::Orbital_PWave(const Tensor& p, const Tensor& q) Tensor AmpGen::Orbital_DWave(const Tensor& p, const Tensor& q) { - Tensor::Index mu; - Tensor::Index nu; Tensor L = Orbital_PWave(p, q); Tensor f = L(mu) * L(nu) - make_cse( dot( L, L ) / 3. ) * Spin1Projector(p) ( mu, nu ); f.imposeSymmetry(0,1); @@ -74,15 +75,12 @@ Tensor AmpGen::Orbital_DWave(const Tensor& p, const Tensor& q) Tensor AmpGen::Spin1Projector( const Tensor& P ) { - Tensor::Index mu; - Tensor::Index nu; auto is = 1./make_cse( dot(P,P) , true); - return Metric4x4()(mu, nu) - P(mu) * P(nu) * is ; // / make_cse( dot(P, P) , true ); + return Metric4x4()(mu, nu) - P(mu) * P(nu) * is; } Tensor AmpGen::Spin2Projector( const Tensor& P ) { - Tensor::Index mu, nu, alpha, beta; Tensor S = Spin1Projector( P ); Tensor SP = -( 1. / 3. ) * S( mu, nu ) * S( alpha, beta ) + (1./2.) * ( S( mu, alpha ) * S( nu, beta ) + S( mu, beta ) * S( nu, alpha ) ) ; return SP; @@ -91,7 +89,6 @@ Tensor AmpGen::Spin2Projector( const Tensor& P ) Tensor AmpGen::Gamma4Vec() { - Tensor::Index a, b, mu; Tensor x( {1, 0, 0, 0}, {4} ); Tensor y( {0, 1, 0, 0}, {4} ); Tensor z( {0, 0, 1, 0}, {4} ); @@ -105,14 +102,11 @@ Tensor AmpGen::slash( const Tensor& P ) ERROR( "Can only compute slash operator against vector currents" ); return Tensor(); } - Tensor::Index mu, a, b; - Tensor rt = Gamma4Vec()( mu, a, b ) * P( -mu ); - return rt; + return Gamma4Vec()( mu, a, b ) * P( -mu ); } Tensor AmpGen::gamma_twiddle( const Tensor& P ) { - Tensor::Index mu, nu, a, b ; Tensor g = Gamma4Vec(); return g(nu,a,b) - P(nu) * P(mu) * g(-mu,a,b) / make_cse( dot(P,P) ); } @@ -125,7 +119,6 @@ Tensor AmpGen::Spin1hProjector( const Tensor& P ) Tensor AmpGen::Spin3hProjector( const Tensor& P ) { - Tensor::Index a,b,c, d, mu, nu; Tensor Ps = P; Ps.st(); Tensor g = gamma_twiddle(Ps); @@ -138,7 +131,6 @@ Tensor AmpGen::Spin3hProjector( const Tensor& P ) } Tensor AmpGen::Bar( const Tensor& P ){ - Tensor::Index a,b; return P.conjugate()(b) * Gamma[3](b,a); } @@ -167,14 +159,7 @@ DEFINE_VERTEX( S_VS_P ) return p_v1 * V2[0] / GeV; } -DEFINE_VERTEX( V_SS_P ) -{ - Tensor p_wave = Orbital_PWave( P, Q ); - Expression scalar_part = V1[0] * V2[0] / GeV; - Tensor L = p_wave * scalar_part; - ADD_DEBUG_TENSOR( L, db ); - return L; -} +DEFINE_VERTEX( V_SS_P ){ return Orbital_PWave(P,Q) * V1[0] * V2[0] / GeV;} DEFINE_VERTEX( V_VS_P ) { @@ -184,11 +169,7 @@ DEFINE_VERTEX( V_VS_P ) } -DEFINE_VERTEX( V_VS_S ) -{ - Tensor L = Spin1Projector(P)(mu,nu) * V1(-nu) * V2[0]; - return L; -} +DEFINE_VERTEX( V_VS_S ){ return Spin1Projector(P)(mu,nu) * V1(-nu) * V2[0]; } DEFINE_VERTEX( V_VS_D ) { @@ -259,24 +240,18 @@ DEFINE_VERTEX( V_TS_D ) DEFINE_VERTEX( f_fS_S ) { - Tensor::Index a,b; return Spin1hProjector(P)(a,b) * V1(b) * V2[0]; } DEFINE_VERTEX( f_fS_P ) { - Tensor::Index a,b,c,d; Tensor proj = Spin1hProjector(P); Tensor L = Orbital_PWave(P,Q); Tensor t = proj(a, b) * Gamma[4](b,c) * slash(L)(c,d) * V1(d); - ADD_DEBUG_TENSOR( L, db ); - ADD_DEBUG_TENSOR( Tensor(Gamma[4](b,c)*slash(L)(c,d)*V1(d)), db ); - ADD_DEBUG_TENSOR(t, db); return t; } DEFINE_VERTEX( f_Vf_S ) { - Tensor::Index a,b,c,d; Tensor proj = Spin1hProjector(P); return proj(a, b) * Gamma[4](b,c) * gamma_twiddle(P)(mu,c,d) * V2(d) * V1(-mu); } @@ -290,7 +265,6 @@ DEFINE_VERTEX( f_Vf_P ) /// = A3 DEFINE_VERTEX( f_Vf_P1 ) //// = A6 { - Tensor::Index a,b,c,d; Tensor proj = Spin1hProjector(P); Tensor L = Orbital_PWave(P,Q); Tensor t = LeviCivita()(mu,nu,alpha,beta) * V1(-nu) * L(-alpha) * P(-beta); @@ -300,7 +274,6 @@ DEFINE_VERTEX( f_Vf_P1 ) //// = A6 DEFINE_VERTEX( f_Vf_D ) //// = A8 { - Tensor::Index a,b,c,d; Tensor proj = Spin1hProjector(P); Tensor gt = gamma_twiddle(P); Tensor L = Orbital_DWave(P,Q)(-mu,-nu) * V1(nu) / (GeV*GeV); @@ -309,28 +282,21 @@ DEFINE_VERTEX( f_Vf_D ) //// = A8 DEFINE_VERTEX( f_Vf_S1 ) { - Tensor::Index a,b,c; Tensor proj = Spin1hProjector(P); Tensor vSlash = gamma_twiddle(P)(mu,a,b) * V1(-mu); return proj( a, b ) * vSlash(b,c) * V2(c); } -DEFINE_VERTEX( f_fS_S1 ) -{ - Tensor::Index a,b,c; - return Spin1hProjector(P)(a,b) * Gamma[4](b,c) * V1(c) * V2[0]; -} +DEFINE_VERTEX( f_fS_S1 ){ return Spin1hProjector(P)(a,b) * Gamma[4](b,c) * V1(c) * V2[0];} DEFINE_VERTEX( f_fS_P1 ) { - Tensor::Index a,b,c,d; return Spin1hProjector(P)(a, b) * slash(Orbital_PWave(P,Q))(b,c) * V1(c) * V2[0] / GeV; } DEFINE_VERTEX( f_Tf_P ) { - Tensor::Index a,b,c; Tensor proj = Spin1hProjector(P); Tensor T = V1; T.imposeSymmetry(0,1); @@ -346,7 +312,6 @@ DEFINE_VERTEX( f_Vf_P2 ) DEFINE_VERTEX( f_Vf_P3 ) { - Tensor::Index a,b,c; Tensor proj = Spin1hProjector(P); Tensor L = Orbital_PWave(P,Q); Tensor t = LeviCivita()(-mu,-nu,-alpha,-beta) * L(nu) * V1(alpha) * P(beta); @@ -357,7 +322,6 @@ DEFINE_VERTEX( f_Vf_P3 ) DEFINE_VERTEX( f_Vf_D1 ) { - Tensor::Index a,b,c,d; Tensor proj = Spin1hProjector(P); Tensor gt = gamma_twiddle(P); Tensor L = Orbital_DWave(P,Q)(-mu,-nu) * V1(nu) / (GeV*GeV); @@ -367,7 +331,6 @@ DEFINE_VERTEX( f_Vf_D1 ) DEFINE_VERTEX( r_fS_P ) { - Tensor::Index a,b,c,d; Tensor L = Orbital_PWave(P,Q); L.st(); Tensor F = Spin1hProjector(P); @@ -378,11 +341,11 @@ DEFINE_VERTEX( r_fS_P ) DEFINE_VERTEX( r_fS_D ) { - Tensor::Index a,b,c,d,e; + Tensor::Index e; Tensor sp = Spin3hProjector(P); Tensor L = Orbital_PWave(P,Q); Tensor F = Spin1hProjector(P); - L.st(1); + L.st(true); Expression L2 = make_cse(dot(L,L)); Tensor gt = gamma_twiddle(P); Tensor rt = ( L(mu) * F(a,b) * slash(L)(b,c) - (L2/3.) * F(a,b) * gt(mu,b,c) ) * Gamma[4](c,d) * V1(d) / (GeV*GeV); @@ -393,7 +356,6 @@ DEFINE_VERTEX( r_fS_D ) DEFINE_VERTEX( f_rS_D ) { - Tensor::Index a,b,c,d; Tensor F = Spin1hProjector(P)(a,b) * Gamma[4](b,d) * gamma_twiddle(P)(mu,d,c) @@ -406,7 +368,6 @@ DEFINE_VERTEX( f_rS_D ) DEFINE_VERTEX( f_rS_P ) { - Tensor::Index a,b,c; auto L = Orbital_PWave(P,Q); Tensor F = Spin1hProjector(P)(a,b) * V1(-mu,b) * L(mu) * V2[0] / GeV; ADD_DEBUG_TENSOR( V1, db ); @@ -418,34 +379,17 @@ DEFINE_VERTEX( f_rS_P ) DEFINE_VERTEX( f_rS_P1 ) { - Tensor::Index a,b,c; auto L = Orbital_PWave(P,Q); Tensor F = Spin1hProjector(P)(a,b) * Gamma[4](b,c) * V1(-mu,c) * L(mu) * V2[0]/ GeV; F.st(); return F; } -DEFINE_VERTEX( S_ff_S ) -{ - Tensor::Index a; - return Bar(V2)(a) * V1(a); -} +DEFINE_VERTEX( S_ff_S ) { return Bar(V2)(a) * V1(a); } -DEFINE_VERTEX( S_ff_S1 ) -{ - Tensor::Index a,b; - return Bar(V2)(a) * Gamma[4](a,b) * V1(b); -} +DEFINE_VERTEX( S_ff_S1 ){ return Bar(V2)(a) * Gamma[4](a,b) * V1(b); } -DEFINE_VERTEX( V_ff_P ) -{ - Tensor::Index a,b ; - return Bar(V2)(a) * Gamma4Vec()(mu,a,b) * V1(b); -} +DEFINE_VERTEX( V_ff_P ) { return Bar(V2)(a) * Gamma4Vec()(mu,a,b) * V1(b); } -DEFINE_VERTEX( V_ff_P1 ) -{ - Tensor::Index a,b,c ; - return Bar(V2)(a) * Gamma[4](a,b) * Gamma4Vec()(mu,b,c) * V1(c); -} +DEFINE_VERTEX( V_ff_P1 ){ return Bar(V2)(a) * Gamma[4](a,b) * Gamma4Vec()(mu,b,c) * V1(c); } diff --git a/src/Wigner.cpp b/src/Wigner.cpp index 06f0f880e46..c09dc3907a2 100644 --- a/src/Wigner.cpp +++ b/src/Wigner.cpp @@ -259,8 +259,9 @@ Expression AmpGen::helicityAmplitude(const Particle& particle, auto& d2 = *particle.daughter(1); double S = 999; if( particle.S() == 0 ){ - for( auto& l : particle_couplings ) if( l.first == L ){ S = l.second ; break; } - if( S == 999 ) ERROR("Spin orbital coupling impossible!"); + auto it = std::find_if( particle_couplings.begin(), particle_couplings.end(), [&L](auto& l){ return l.second == L; } ); + if( it != particle_couplings.end() ) S = it->second; + else ERROR("Spin orbital coupling impossible!"); } else S = particle.S()/2.; auto recoupling_constants = calculate_recoupling_constants( particle.spin(), Mz, L, S, d1.spin(), d2.spin() ); diff --git a/test/test_AmplitudeRules.cpp b/test/test_AmplitudeRules.cpp new file mode 100644 index 00000000000..47379a54a0e --- /dev/null +++ b/test/test_AmplitudeRules.cpp @@ -0,0 +1,55 @@ +#define BOOST_TEST_DYN_LINK + +#define BOOST_TEST_MODULE "ArgumentPack" + +#include +namespace utf = boost::unit_test; + +#include "AmpGen/AmplitudeRules.h" +#include "AmpGen/MinuitParameter.h" +#include "AmpGen/MinuitParameterSet.h" + +using namespace AmpGen; + +BOOST_AUTO_TEST_CASE( test_AmplitudeRule ) { + + MinuitParameter re = MinuitParameter("D0{K*(892)bar0{K-,pi+},pi0}_Re",MinuitParameter::Flag::Float,1.,0.); + MinuitParameter im = MinuitParameter("D0{K*(892)bar0{K-,pi+},pi0}_Im",MinuitParameter::Flag::Float,0.,0.); + + AmplitudeRule test(&re,&im); + + BOOST_CHECK( test.name() == "D0{K*(892)bar0{K-,pi+},pi0}" ); + BOOST_CHECK( test.head() == "D0"); + BOOST_CHECK( test.prefix() == "" ); + BOOST_CHECK( test.eventType() == EventType({"D0","K-","pi+","pi0"}) ); +} +AmplitudeRules rule_set( + MinuitParameterSet( { + new MinuitParameter("D0{K*(892)bar0,pi0}_Re", MinuitParameter::Flag::Fix,1.,0.) + , new MinuitParameter("D0{K*(892)bar0,pi0}_Im", MinuitParameter::Flag::Fix,1.,0.) + , new MinuitParameter("D0{rho(770)+,pi-}_Re" , MinuitParameter::Flag::Fix,1.,0.) + , new MinuitParameter("D0{rho(770)+,pi-}_Im" , MinuitParameter::Flag::Fix,2.,0.) + , new MinuitParameter("K*(892)bar0{K-,pi+}_Re", MinuitParameter::Flag::Float,sqrt(1./3.),0.) + , new MinuitParameter("K*(892)bar0{K-,pi+}_Im", MinuitParameter::Flag::Float,0,0.) + , new MinuitParameter("K*(892)bar0{K0,pi0}_Re", MinuitParameter::Flag::Fix,sqrt(2./3.),0.) + , new MinuitParameter("K*(892)bar0{K0,pi0}_Im", MinuitParameter::Flag::Fix,0,0.) } ) ); + +BOOST_AUTO_TEST_CASE( test_AmplitudeRules_constructor ){ + BOOST_CHECK( rule_set.rules().size() == 2 ); /// number of head decays + BOOST_CHECK( rule_set.hasDecay("D0") == true ); /// has decays for D0 + BOOST_CHECK( rule_set.hasDecay("a(1)(1260)+") == false ); /// has decays for D0 +} + +BOOST_AUTO_TEST_CASE( test_couplingConstant ) +{ + auto matches = rule_set.getMatchingRules( EventType({"D0","K-","pi+","pi0"}) ); + auto matches2 = rule_set.getMatchingRules( EventType({"D0","K0","pi0","pi0"}) ); + + BOOST_TEST( std::real(matches[0].second()) == 1./sqrt(3.), boost::test_tools::tolerance(1e-10) ); + BOOST_TEST( std::imag(matches[0].second()) == 1./sqrt(3.), boost::test_tools::tolerance(1e-10) ); + BOOST_TEST( matches[0].second.isFixed() == false ); + BOOST_TEST( matches2[0].second.isFixed() == true ); + BOOST_TEST( matches[0].second.contains("K*(892)bar0{K0,pi0}") == false ); + BOOST_TEST( matches2[0].second.contains("K*(892)bar0{K0,pi0}") == true ); +} + diff --git a/test/test_ArgumentPack.cpp b/test/test_ArgumentPack.cpp index 0d529a25284..437a9fa4173 100644 --- a/test/test_ArgumentPack.cpp +++ b/test/test_ArgumentPack.cpp @@ -7,13 +7,15 @@ namespace utf = boost::unit_test; #include "AmpGen/ArgumentPack.h" -DECLARE_ARGUMENT_DEFAULT( test_argument_string, std::string, "hello world"); +DECLARE_ARGUMENT( test_argument_string, std::string); DECLARE_ARGUMENT( test_argument_double , double ); +static const test_argument_double value; + struct Mock { Mock( const AmpGen::ArgumentPack& args ){ t1 = args.getArg().val; - t2 = args.getArg().val; + t2 = args.getArg("hello world").val; } template Mock( const ARGS&... args ) : Mock( AmpGen::ArgumentPack(args...) ) {} From 1ebb9d7700f4e0d0727e2eba54beaf69f66e23d7 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 23 May 2019 13:57:33 +0200 Subject: [PATCH 060/250] Greatly improved parser for expression parameters, added unit tests for ExpressionParser --- AmpGen/CoherentSum.h | 2 - AmpGen/ExpressionParser.h | 3 +- AmpGen/MinuitExpression.h | 5 +- AmpGen/MinuitParameterSet.h | 1 - src/AmplitudeRules.cpp | 4 +- src/CoherentSum.cpp | 25 +++----- src/EventType.cpp | 12 ++-- src/ExpressionParser.cpp | 104 +++++++++++++++++++-------------- src/MinuitParameterSet.cpp | 8 ++- src/ParticleProperties.cpp | 9 --- src/ParticlePropertiesList.cpp | 30 +++------- src/Spline.cpp | 4 +- src/Tensor.cpp | 5 +- src/Utilities.cpp | 6 +- src/Wigner.cpp | 2 +- test/test_AmplitudeRules.cpp | 2 +- test/test_ExpressionParser.cpp | 64 ++++++++++++++++++++ 17 files changed, 163 insertions(+), 123 deletions(-) create mode 100644 test/test_ExpressionParser.cpp diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index 3bc13256d47..015dcf6779f 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -96,8 +96,6 @@ namespace AmpGen std::string m_objCache = {""}; ///< Directory that contains (cached) amplitude objects std::string m_prefix = {""}; ///< Prefix for matrix elements void addMatrixElement( std::pair& particleWithCoupling, const MinuitParameterSet& mps ); - bool isFixedPDF(const MinuitParameterSet& mps) const; - }; } // namespace AmpGen diff --git a/AmpGen/ExpressionParser.h b/AmpGen/ExpressionParser.h index 42c789575c0..a89562b7fde 100644 --- a/AmpGen/ExpressionParser.h +++ b/AmpGen/ExpressionParser.h @@ -68,12 +68,11 @@ namespace AmpGen if ( !gExpressionParser ) gExpressionParser = new ExpressionParser(); return gExpressionParser; } - private: ExpressionParser(); Expression processEndPoint( const std::string& name ); - Expression parseTokens( const std::vector& tokens ); + Expression parseTokens( const std::vector::iterator& begin, const std::vector::iterator& end ); void processBinaryOperators( std::vector& opCodes, std::vector& expressions ); void processUnaryOperators( std::vector& opCodes, std::vector& expressions ); diff --git a/AmpGen/MinuitExpression.h b/AmpGen/MinuitExpression.h index 377dd01de6d..f4a7179e5e3 100644 --- a/AmpGen/MinuitExpression.h +++ b/AmpGen/MinuitExpression.h @@ -20,13 +20,10 @@ namespace AmpGen public: MinuitExpression( const std::vector& tokens, MinuitParameterSet* mps ); - double getVal() const { return std::real( m_expression() ); } + double mean() const override { return getVal(); } operator double() const override { return getVal(); } - ~MinuitExpression() override = default; - - double mean() const override { return getVal(); } bool isGood() const { return m_isGood; } }; } // namespace AmpGen diff --git a/AmpGen/MinuitParameterSet.h b/AmpGen/MinuitParameterSet.h index 75b0b736307..223269cdc27 100644 --- a/AmpGen/MinuitParameterSet.h +++ b/AmpGen/MinuitParameterSet.h @@ -61,7 +61,6 @@ namespace AmpGen bool addToEnd( MinuitParameter* parPtr ); std::vector m_parameters; - std::vector m_expressions; std::map m_keyAccess; }; } // namespace AmpGen diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index bba12f03a35..5ef8d561944 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -184,8 +184,8 @@ std::vector> AmplitudeRules::getMatchingRu bool CouplingConstant::isFixed() const { - return ! std::any_of( couplings.begin(), couplings.end(), - [](auto& c){ return c.first->iFixInit() == 0 or c.second->iFixInit() == 0 ; } ); + return std::all_of( couplings.begin(), couplings.end(), + [](auto& c){ return c.first->iFixInit() != 0 && c.second->iFixInit() != 0 ; } ); } bool CouplingConstant::contains( const std::string& label ) const diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 1e509da4798..493e195a861 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -50,9 +50,9 @@ CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, m_matrixElements[i] = TransitionMatrix( amplitudes[i].first, amplitudes[i].second, mps, this->m_evtType.getEventFormat(), this->m_dbThis); CompilerWrapper().compile( m_matrixElements[i].pdf, this->m_objCache); } ); } - m_isConstant = false ; // isFixedPDF(mps); + m_isConstant = false ; } - + void CoherentSum::prepare() { if ( m_weightParam != nullptr ) m_weight = m_weightParam->mean(); @@ -100,9 +100,9 @@ void CoherentSum::prepare() void CoherentSum::updateNorms( const std::vector& changedPdfIndices ) { for ( auto& i : changedPdfIndices ) m_integrator.prepareExpression( m_matrixElements[i].pdf ); - std::vector cacheIndex; - for( auto& m : m_matrixElements ) - cacheIndex.push_back( m_integrator.events().getCacheIndex( m.pdf ) ); + std::vector cacheIndex; + std::transform( m_matrixElements.begin(), m_matrixElements.end(), std::back_inserter(cacheIndex), + [this](auto& m){ return this->m_integrator.events().getCacheIndex( m.pdf ) ; } ); for ( auto& i : changedPdfIndices ) for ( size_t j = 0; j < size(); ++j ) m_integrator.queueIntegral( cacheIndex[i], cacheIndex[j] ,i, j, &m_normalisations ); @@ -145,7 +145,7 @@ std::vector CoherentSum::fitFractions(const LinearErrorPropagator& } if( pCalc.calculators.size() == 0 ) continue; auto fractions = pCalc(rule.first, linProp); - for( auto& f : fractions ) outputFractions.emplace_back(f); + std::transform( fractions.begin(), fractions.end(), std::back_inserter(outputFractions),[](auto& p){ return p;} ); }; auto ffForHead = m_protoAmplitudes.rulesForDecay(m_evtType.mother(), m_prefix); FitFractionCalculator iCalc(this, findIndices(m_matrixElements, m_evtType.mother()), recomputeIntegrals); @@ -252,14 +252,6 @@ void CoherentSum::generateSourceCode(const std::string& fname, const double& nor stream.close(); } -bool CoherentSum::isFixedPDF(const MinuitParameterSet& mps) const -{ - for ( auto& matrixElement : m_matrixElements ) { - if( ! matrixElement.coupling.isFixed() ) return false; - } - return true; -} - complex_t CoherentSum::getValNoCache( const Event& evt ) const { return std::accumulate( m_matrixElements.begin(), @@ -347,9 +339,8 @@ void CoherentSum::printVal(const Event& evt) std::vector CoherentSum::cacheAddresses( const EventList& evts ) const { std::vector addresses; - for ( auto& mE : m_matrixElements ) { - addresses.push_back( evts.getCacheIndex( mE.pdf ) ); - } + std::transform( m_matrixElements.begin(), m_matrixElements.end(), std::back_inserter(addresses), + [&evts](auto& it ){ return evts.getCacheIndex( it.pdf ) ; } ); return addresses; } diff --git a/src/EventType.cpp b/src/EventType.cpp index 03bed2e05a9..b7b49e91298 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -146,8 +146,8 @@ EventType EventType::conj( const bool& headOnly, const bool& dontConjHead ) cons { std::vector type; type.push_back( dontConjHead ? m_mother : ParticlePropertiesList::get( m_mother )->anti().name() ); - - for ( auto& x : m_particleNames ) type.push_back( headOnly ? x : ParticlePropertiesList::get( x )->anti().name() ); + std::transform( m_particleNames.begin(), m_particleNames.end(), std::back_inserter(type), + [&](auto& x){ return headOnly ? x : ParticlePropertiesList::get(x)->anti().name() ; } ); return EventType( type ); } @@ -157,8 +157,8 @@ std::vector EventType::defaultProjections(const size_t& nBins) const std::vector projections; for ( size_t r = 2; r < size(); ++r ) { /// loop over sizes /// std::vector> combR = nCr( size(), r ); - for ( auto& indices : combR ) - projections.emplace_back( projection(nBins, indices, defaultObservable ) ); + std::transform( combR.begin(), combR.end(), std::back_inserter(projections), + [&](auto& index){ return projection(nBins, index, defaultObservable ) ; } ); } return projections; } @@ -226,9 +226,7 @@ std::function EventType::symmetriser() const bool EventType::has( const std::string& name ) const { - for ( auto& it : m_particleNames ) - if ( it == name ) return true; - return false; + return std::any_of( m_particleNames.begin(), m_particleNames.end(), [&name](auto& it) { return it == name ; } ); } bool EventType::isTimeDependent() const { return m_timeDependent; } diff --git a/src/ExpressionParser.cpp b/src/ExpressionParser.cpp index 338710c4abb..517cc8633b6 100644 --- a/src/ExpressionParser.cpp +++ b/src/ExpressionParser.cpp @@ -18,7 +18,7 @@ DEFINE_CAST( ExpressionPack ) void ExpressionParser::processBinaryOperators( std::vector& opCodes, std::vector& expressions ) { for ( auto& fcn : m_binaryFunctions ) { - for ( int pos = 0; pos < (int)opCodes.size(); ++pos ) { + for ( int pos = 0; pos < int(opCodes.size()); ++pos ) { if ( opCodes[pos] != fcn.first ) continue; expressions[pos] = fcn.second( expressions[pos], expressions[pos + 1] ); expressions.erase( expressions.begin() + pos + 1 ); @@ -30,7 +30,7 @@ void ExpressionParser::processBinaryOperators( std::vector& opCodes void ExpressionParser::processUnaryOperators( std::vector& opCodes, std::vector& expressions ) { - for ( int pos = 0; pos < (int)opCodes.size(); ++pos ) { + for ( int pos = 0; pos < int(opCodes.size()); ++pos ) { auto fcn = m_unaryFunctions.find( opCodes[pos] ); DEBUG( " op = " << opCodes[pos] << " pos = " << pos ); if ( fcn == m_unaryFunctions.end() ) continue; @@ -40,37 +40,47 @@ void ExpressionParser::processUnaryOperators( std::vector& opCodes, } } -Expression ExpressionParser::parseTokens( const std::vector& tokens ) +std::vector::iterator findMatchingBracket( + const std::vector::iterator& begin, + const std::vector::iterator& end ) { - int nOpenedBrackets = 0; - std::vector> expressions; - expressions.push_back( std::vector() ); - for ( auto iToken = tokens.begin(); iToken != tokens.end(); ++iToken ) { - auto& token = *iToken; - expressions.rbegin()->push_back( token ); - if ( token == "(" ) nOpenedBrackets++; - if ( token == ")" ) nOpenedBrackets--; - if ( nOpenedBrackets == 0 && iToken != tokens.end() - 1 ) expressions.push_back( std::vector() ); + int openedBrackets = 1; + if( begin + 1 >= end ) return end; + for( auto it = begin+1; it != end; ++it ) + { + if( *it == "(") openedBrackets++; + if( *it == ")" ) openedBrackets--; + if( openedBrackets == 0 ) return it; } - for ( auto& eC : expressions ) { - if ( eC.size() > 2 && *eC.begin() == "(" && *eC.rbegin() == ")" ) { - eC.erase( eC.end() - 1 ); - eC.erase( eC.begin() ); - } - } - if ( expressions.size() == 1 ) return processEndPoint( expressions[0][0] ); + ERROR("Unmatched brace in expression"); + return end; +} +Expression ExpressionParser::parseTokens( const std::vector::iterator& begin, + const std::vector::iterator& end ) +{ std::vector opCodes; - std::vector parsedExpressions; - for ( size_t pos = 0; pos < expressions.size(); pos++ ) { - if ( pos % 2 == expressions.size() % 2 ) - opCodes.push_back( expressions[pos][0] ); - else - parsedExpressions.push_back( parseTokens( expressions[pos] ) ); + std::vector expressions; + for( auto it = begin; it != end; ++it ) + { + if( *it == "(" ){ + auto begin_2 = it; + auto end_2 = findMatchingBracket(it, end); + expressions.emplace_back( parseTokens(begin_2+1, end_2) ); + it = end_2; + } + else { + auto f = std::find_if(m_binaryFunctions.begin(), m_binaryFunctions.end(), [it](auto& jt){ return jt.first == *it; } ); + if( f != m_binaryFunctions.end() || m_unaryFunctions.count(*it) ) opCodes.push_back(*it); + else expressions.push_back( processEndPoint( *it ) ); + } + } + processUnaryOperators( opCodes, expressions ); + processBinaryOperators( opCodes, expressions ); + if( expressions.size() != 1 ){ + ERROR("Could not process expression!"); } - processUnaryOperators( opCodes, parsedExpressions ); - processBinaryOperators( opCodes, parsedExpressions ); - return parsedExpressions[0]; + return expressions[0]; } ExpressionParser::ExpressionParser() : m_mps( nullptr ) @@ -86,31 +96,37 @@ ExpressionParser::ExpressionParser() : m_mps( nullptr ) add_unary( "sqrt" ); add_unary( "exp" ); add_unary( "log" ); - - add_binary( "/", []( auto& A, auto& B ) { return A / B; } ); /// operator ordering here matters! - add_binary( "*", []( auto& A, auto& B ) { return A * B; } ); - add_binary( "+", []( auto& A, auto& B ) { return A + B; } ); - add_binary( "-", []( auto& A, auto& B ) { return A - B; } ); - add_binary( ">", []( auto& A, auto& B ) { return A > B; } ); - add_binary( "<", []( auto& A, auto& B ) { return A < B; } ); + add_unary("real"); + add_unary("imag"); + add_unary("abs"); + + add_binary( "^" , [](auto& A, auto& B ) { return fcn::pow(A,B); } ); + add_binary( "/" , [](auto& A, auto& B ) { return A / B; } ); + add_binary( "*" , [](auto& A, auto& B ) { return A * B; } ); + add_binary( "+" , [](auto& A, auto& B ) { return A + B; } ); + add_binary( "-" , [](auto& A, auto& B ) { return A - B; } ); + add_binary( ">" , [](auto& A, auto& B ) { return A > B; } ); + add_binary( "<" , [](auto& A, auto& B ) { return A < B; } ); add_binary( "&&", []( auto& A, auto& B ) { return A && B; } ); - add_binary( ",", []( auto& A, auto& B ) { return ExpressionPack( A, B ); } ); + add_binary( "," , []( auto& A, auto& B ) { return ExpressionPack( A, B ); } ); } -Expression ExpressionParser::Parse( const std::string& str ) { return getMe()->parseTokens( split( str, ' ' ) ); } +Expression ExpressionParser::Parse( const std::string& str ) { + auto tokens = split(str, ' '); + return getMe()->parseTokens(tokens.begin(), tokens.end() ); +} ExpressionParser* ExpressionParser::gExpressionParser = nullptr; Expression ExpressionParser::processEndPoint( const std::string& name ) { bool status = true; double value = lexical_cast( name, status ); - if ( status == true ) return Constant( value ); - if ( name == "PI" ) return Constant( M_PI ); - if ( name == "pi" ) return Constant( M_PI ); - if ( name == "e" ) return Constant( std::exp(1) ); - if ( name == "I" ) return Constant( 0, 1 ); - if ( name == "i" ) return Constant( 0, 1 ); - + if ( status == true ) return value; + if ( name == "PI" ) return M_PI; + if ( name == "pi" ) return M_PI; + if ( name == "e" ) return std::exp(1); + if ( name == "I" ) return complex_t( 0, 1 ); + if ( name == "i" ) return complex_t( 0, 1 ); if ( m_mps != nullptr ) { auto it = m_mps->find(name); if ( it != nullptr ) return MinuitParameterLink( it ); diff --git a/src/MinuitParameterSet.cpp b/src/MinuitParameterSet.cpp index b14964f2f59..429d5bdfa84 100644 --- a/src/MinuitParameterSet.cpp +++ b/src/MinuitParameterSet.cpp @@ -32,7 +32,9 @@ MinuitParameterSet MinuitParameterSet::getFloating() { MinuitParameterSet floating; for ( auto& param : *this ) { - if ( param->iFixInit() == MinuitParameter::Flag::Float ) floating.add(param); + if ( param->iFixInit() == MinuitParameter::Flag::Float && + dynamic_cast(param) != nullptr + ) floating.add(param); } return floating; } @@ -193,8 +195,8 @@ void MinuitParameterSet::tryAlias( const std::vector& line ) std::string name = line[0]; MinuitExpression* expr = new MinuitExpression( line, this ); if ( expr->isGood() ) { - m_expressions.push_back( expr ); - m_keyAccess[name] = expr; + addToEnd( expr ); + // m_keyAccess[name] = expr; } else { ERROR( "Expression is ill-formed: " << line[0] ); delete expr; diff --git a/src/ParticleProperties.cpp b/src/ParticleProperties.cpp index d0d67fc2906..680a9c4c744 100644 --- a/src/ParticleProperties.cpp +++ b/src/ParticleProperties.cpp @@ -91,15 +91,6 @@ void ParticleProperties::setRadius() m_Radius = isCharm ? defaultCharmRadius : defaultRadius; } -void swap_string(std::string& arg, const char a, const char b) -{ - for( auto& c : arg ) - { - if( c == a ) c = b; - else if( c == b ) c = a; - } -} - void ParticleProperties::antiQuarks() { if ( m_quarks.empty() ) return; diff --git a/src/ParticlePropertiesList.cpp b/src/ParticlePropertiesList.cpp index 68fb8c58e07..c3a507a2b9a 100644 --- a/src/ParticlePropertiesList.cpp +++ b/src/ParticlePropertiesList.cpp @@ -17,18 +17,14 @@ ParticlePropertiesList* ParticlePropertiesList::ptr = nullptr; const ParticlePropertiesList* ParticlePropertiesList::getMe() { - if(!ptr){ - ptr = new ParticlePropertiesList(); - } + if(!ptr) ptr = new ParticlePropertiesList(); if(nullptr == ptr) FATAL("Couldn't get ParticlePropertiesList (i.e. myself)" ); return ptr; } ParticlePropertiesList* ParticlePropertiesList::getMutable() { - if(!ptr){ - ptr = new ParticlePropertiesList(); - } + if(!ptr) ptr = new ParticlePropertiesList(); if(ptr == nullptr) FATAL( "Couldn't get ParticlePropertiesList (i.e. myself)" ); return ptr; } @@ -72,17 +68,13 @@ const std::vector ParticlePropertiesList::dirList() const ParticlePropertiesList::ParticlePropertiesList( const std::string& fname_in ) { - - auto _dirList = dirList(); - - for ( auto& d : _dirList ) { - if ( readLatexLabels( d + "pdgID_to_latex.dat" ) ) break; - } - for ( auto& d : _dirList ) { - if ( readFile( d + "mass_width.csv" ) ) break; - } - for ( auto& d : _dirList ) { - if ( readFile( d + "MintDalitzSpecialParticles.csv" ) ) break; + auto dl = dirList(); + bool status = true; + status &= std::any_of( dl.begin(), dl.end(), [this](auto& d){ return this->readLatexLabels(d +"pdgID_to_latex.dat") ; } ); + status &= std::any_of( dl.begin(), dl.end(), [this](auto& d){ return this->readFile(d +"mass_width.csv") ; } ); + status &= std::any_of( dl.begin(), dl.end(), [this](auto& d){ return this->readFile(d +"MintDalitzSpecialParticles.csv") ; } ); + if( !status ){ + WARNING("Failed to load full PDG configuration, beware of unexpected behaviour"); } makeMappings(); m_quasiStableThreshold = NamedParameter( "ParticleProperties::qsThreshold", KeV ); /// limit is 1 keV @@ -90,15 +82,12 @@ ParticlePropertiesList::ParticlePropertiesList( const std::string& fname_in ) bool ParticlePropertiesList::readLatexLabels( const std::string& name ) { - if ( !fileExists( name ) ) return false; - m_latexLabels.clear(); processFile( name, [this]( auto& line ) { auto tokens = split( line, ' ' ); this->m_latexLabels[stoi( tokens[0] )] = std::make_pair( tokens[1], tokens[2] ); } ); - return true; } @@ -117,7 +106,6 @@ bool ParticlePropertiesList::readFile( const std::string& name ) WARNING( line << " is not valid" ); return; } - auto label = m_latexLabels.find( P.pdgID() ); if ( label != m_latexLabels.end() ) P.setLabel( label->second.first ); m_theList.push_back( P ); diff --git a/src/Spline.cpp b/src/Spline.cpp index 88d177fc789..6efb89eb628 100644 --- a/src/Spline.cpp +++ b/src/Spline.cpp @@ -117,9 +117,7 @@ SplineTransfer::SplineTransfer( const unsigned int& address, const unsigned int& bool SplineTransfer::isConfigured() { - for ( auto& x : m_parameters ) - if ( x == nullptr ) return false; - return true; + return std::all_of( m_parameters.begin(), m_parameters.end(), [](auto& p ){ return p != nullptr ; } ); } void SplineTransfer::set( const unsigned int& N, MinuitParameter* f ) diff --git a/src/Tensor.cpp b/src/Tensor.cpp index bc0a712903a..2eadbae90f1 100644 --- a/src/Tensor.cpp +++ b/src/Tensor.cpp @@ -63,9 +63,8 @@ size_t Tensor::rank() const { return m_dim.size(); } int Tensor::metricSgn( const std::vector& coordinates ) const { - int sgn = 1; - for ( auto& coord : coordinates ) sgn *= ( coord == 3 ) ? 1 : -1; - return sgn; + return std::accumulate( coordinates.begin(), coordinates.end(), 1, + [](auto& prod, auto& co){ return prod * ( ( co == 3) ? 1 : -1 ) ;} ); } int Tensor::metricSgn( const size_t& index ) const { return metricSgn( coords( index ) ); } diff --git a/src/Utilities.cpp b/src/Utilities.cpp index 950747848cd..2d0768ebf47 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -112,13 +112,13 @@ std::string AmpGen::replaceAll( const std::string& input, const std::string& toR // where Y and Z and A are also tree elements, by finding // the matching delimiter and the Z, A elements. -std::vector AmpGen::getItems( const std::string& tree, const std::vector& brackets, - const std::string& seperator ) +std::vector AmpGen::getItems( const std::string& tree, + const std::vector& brackets, + const std::string& seperator ) { auto braces = vecFindAll( tree, brackets ); /// get a vector of positions of the brackets /// if ( braces.size() % 2 != 0 ) { ERROR( "Unmatched braces in expression: " << tree << " check string: " << braces.size() ); - for ( auto& x : braces ) INFO( "char[" << x.first << "] = " << x.second ); return std::vector(); } diff --git a/src/Wigner.cpp b/src/Wigner.cpp index c09dc3907a2..d68f5118845 100644 --- a/src/Wigner.cpp +++ b/src/Wigner.cpp @@ -259,7 +259,7 @@ Expression AmpGen::helicityAmplitude(const Particle& particle, auto& d2 = *particle.daughter(1); double S = 999; if( particle.S() == 0 ){ - auto it = std::find_if( particle_couplings.begin(), particle_couplings.end(), [&L](auto& l){ return l.second == L; } ); + auto it = std::find_if( particle_couplings.begin(), particle_couplings.end(), [&L](auto& l){ return l.first == L; } ); if( it != particle_couplings.end() ) S = it->second; else ERROR("Spin orbital coupling impossible!"); } diff --git a/test/test_AmplitudeRules.cpp b/test/test_AmplitudeRules.cpp index 47379a54a0e..1a039af09d6 100644 --- a/test/test_AmplitudeRules.cpp +++ b/test/test_AmplitudeRules.cpp @@ -1,6 +1,6 @@ #define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MODULE "ArgumentPack" +#define BOOST_TEST_MODULE "AmplitudeRules" #include namespace utf = boost::unit_test; diff --git a/test/test_ExpressionParser.cpp b/test/test_ExpressionParser.cpp new file mode 100644 index 00000000000..acb6e761a9b --- /dev/null +++ b/test/test_ExpressionParser.cpp @@ -0,0 +1,64 @@ +#define BOOST_TEST_DYN_LINK + +#define BOOST_TEST_MODULE "ExpressionParser" + +#include +namespace utf = boost::unit_test; + +#include "AmpGen/ExpressionParser.h" +#include "AmpGen/MinuitParameterSet.h" + +using namespace AmpGen; + +BOOST_AUTO_TEST_CASE( test_ExpressionParser ) { + + double a = 1.0; + double b = 0.5; + + MinuitParameterSet mps( { + new MinuitParameter("a",MinuitParameter::Flag::Float, a,0. ) + , new MinuitParameter("b",MinuitParameter::Flag::Float, b,0. ) + }); + ExpressionParser::getMe()->setMPS( &mps ); + + double pi = M_PI; + + auto test = [](const std::string& expr) -> double { + std::string newLine=""; + for( auto& ch : expr ){ + if( ch == '(' || + ch == ')' || + ch == '+' || + ch == '-' || + ch == '*' || + ch == '/' || + ch == '>' || + ch == '<' || + ch == '^' ){ + newLine.push_back(' '); + newLine.push_back(ch); + newLine.push_back(' '); + } + else newLine.push_back(ch); + } + return std::real( ExpressionParser::Parse(newLine)() ); }; + + BOOST_CHECK( test("a+(cos(b-sin(2/a*pi))-sin(a-cos(2*b/pi)))-b") == a+(cos(b-sin(2/a*pi))-sin(a-cos(2*b/pi)))-b ); + BOOST_CHECK( test("sin(a)+sin(b)") == sin(a)+sin(b) ); + BOOST_CHECK( test("abs(sin(sqrt(a^2+b^2))*255)") == abs(sin(sqrt(a*a+b*b))*255) ); + BOOST_CHECK( test("sqrt(a) Date: Thu, 23 May 2019 14:34:57 +0200 Subject: [PATCH 061/250] Remove c++17 only code in ArgumentPack, minor tweaks to MinuitExpression handling --- AmpGen/ArgumentPack.h | 7 ++----- AmpGen/BinDT.h | 1 - src/ExpressionParser.cpp | 7 ++++++- src/MinuitExpression.cpp | 1 + src/MinuitParameterSet.cpp | 1 - 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/AmpGen/ArgumentPack.h b/AmpGen/ArgumentPack.h index 9dad136ee7c..54c1681d917 100644 --- a/AmpGen/ArgumentPack.h +++ b/AmpGen/ArgumentPack.h @@ -45,12 +45,9 @@ namespace AmpGen { template Argument( T x ) : val(x) {} - Argument() { - if constexpr(std::is_pointer_v) val = nullptr; - else val = TYPE(); - } + Argument() = default; operator TYPE() const { return val; } - TYPE val; + TYPE val = { TYPE() }; }; struct File : public IArgument diff --git a/AmpGen/BinDT.h b/AmpGen/BinDT.h index c8a2fdb271f..c4140e242a0 100644 --- a/AmpGen/BinDT.h +++ b/AmpGen/BinDT.h @@ -26,7 +26,6 @@ namespace AmpGen DECLARE_ARGUMENT(MaxDepth, size_t ); DECLARE_ARGUMENT(MinEvents, size_t ); DECLARE_ARGUMENT(Dim, size_t ); - DECLARE_ARGUMENT(Stream, std::ifstream* ); DECLARE_ARGUMENT(Functor, std::function( const Event& )>); class BinDT diff --git a/src/ExpressionParser.cpp b/src/ExpressionParser.cpp index 517cc8633b6..8758d58bcb8 100644 --- a/src/ExpressionParser.cpp +++ b/src/ExpressionParser.cpp @@ -11,6 +11,7 @@ #include "AmpGen/ASTResolver.h" using namespace AmpGen; +using namespace std::complex_literals; DEFINE_CAST( MinuitParameterLink ) DEFINE_CAST( ExpressionPack ) @@ -130,8 +131,12 @@ Expression ExpressionParser::processEndPoint( const std::string& name ) if ( m_mps != nullptr ) { auto it = m_mps->find(name); if ( it != nullptr ) return MinuitParameterLink( it ); - else { + else if ( m_mps->find(name+"_Re") != nullptr && m_mps->find(name+"_Im") != nullptr ) { + return MinuitParameterLink( m_mps->find(name+"_Re") ) + 1i * MinuitParameterLink( m_mps->find(name+"_Im") ); + } + else { WARNING( "Token not understood: " << name << " [map size = " << m_mps->size() << "]" ); + for( auto& m : *m_mps ) INFO( m->name() ); } } return Parameter( name, 0, true ); diff --git a/src/MinuitExpression.cpp b/src/MinuitExpression.cpp index 1625781e92f..0988a49f595 100644 --- a/src/MinuitExpression.cpp +++ b/src/MinuitExpression.cpp @@ -17,4 +17,5 @@ MinuitExpression::MinuitExpression( const std::vector& tokens, Minu ExpressionParser::getMe()->setMPS( mps ); m_expression = ExpressionParser::Parse( total_line ); m_isGood = true; + fix(); } diff --git a/src/MinuitParameterSet.cpp b/src/MinuitParameterSet.cpp index 429d5bdfa84..e6bfe3aaa18 100644 --- a/src/MinuitParameterSet.cpp +++ b/src/MinuitParameterSet.cpp @@ -196,7 +196,6 @@ void MinuitParameterSet::tryAlias( const std::vector& line ) MinuitExpression* expr = new MinuitExpression( line, this ); if ( expr->isGood() ) { addToEnd( expr ); - // m_keyAccess[name] = expr; } else { ERROR( "Expression is ill-formed: " << line[0] ); delete expr; From 2c4775171292804043e58b06e0817707d000f66b Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 23 May 2019 14:42:41 +0200 Subject: [PATCH 062/250] Fix mixing object in EventType --- src/EventType.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EventType.cpp b/src/EventType.cpp index b7b49e91298..12ba74af9c9 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -158,7 +158,7 @@ std::vector EventType::defaultProjections(const size_t& nBins) const for ( size_t r = 2; r < size(); ++r ) { /// loop over sizes /// std::vector> combR = nCr( size(), r ); std::transform( combR.begin(), combR.end(), std::back_inserter(projections), - [&](auto& index){ return projection(nBins, index, defaultObservable ) ; } ); + [&](auto& index){ return this->projection(nBins, index, defaultObservable ); } ); } return projections; } From d8b31d569063f313f899b7e2a2f44f2d78e0bcd5 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 23 May 2019 14:49:44 +0200 Subject: [PATCH 063/250] add optional OPENMP off switch to QcGenerator --- examples/QcGenerator.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp index 058c249a3ae..096b4bf68ff 100644 --- a/examples/QcGenerator.cpp +++ b/examples/QcGenerator.cpp @@ -11,8 +11,10 @@ #include #include #include -#include -#include +#ifdef _OPENMP + #include + #include +#endif using namespace AmpGen; using namespace std::complex_literals; From ae9aca7a2a0faca0d028ae7ca8628486e3d1f578 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 23 May 2019 15:00:32 +0200 Subject: [PATCH 064/250] properly flag OPENMP in QcGenerator.. --- examples/QcGenerator.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp index 096b4bf68ff..187ac775991 100644 --- a/examples/QcGenerator.cpp +++ b/examples/QcGenerator.cpp @@ -222,9 +222,11 @@ int main( int argc, char** argv ) auto tags = NamedParameter("TagTypes" , std::string(), "Vector of opposite side tags to generate, in the format \033[3m outputTreeName decayDescriptor \033[0m.").getVector(); gRandom = new TRandom3(seed); + #ifdef _OPENMP omp_set_num_threads( nThreads ); INFO("Setting " << nThreads << " fixed threads for OpenMP"); omp_set_dynamic(0); + #endif MinuitParameterSet MPS; MPS.loadFromStream(); add_CP_conjugate( MPS ); From e0d02d804875a46a2befb9073b4125fd6783e563 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 24 May 2019 10:12:45 +0200 Subject: [PATCH 065/250] Add more of the recommendations for cppcheck, some unit tests for QuarkContent --- AmpGen/ExpressionParser.h | 11 +++++---- AmpGen/QuarkContent.h | 5 ++-- src/ExpressionParser.cpp | 45 ++++++++++++++++++++-------------- src/FastDT.cpp | 2 +- src/FitResult.cpp | 4 +-- src/MinuitExpression.cpp | 5 +--- src/MinuitParameterSet.cpp | 3 +-- src/Particle.cpp | 3 ++- src/ParticlePropertiesList.cpp | 4 +-- src/QuarkContent.cpp | 10 ++++++++ src/RecursivePhaseSpace.cpp | 3 +-- src/Simplify.cpp | 7 +++--- src/Tensor.cpp | 21 ++++++---------- test/test_ExpressionParser.cpp | 5 ++-- test/test_QuarkContent.cpp | 24 ++++++++++++++++++ 15 files changed, 93 insertions(+), 59 deletions(-) create mode 100644 test/test_QuarkContent.cpp diff --git a/AmpGen/ExpressionParser.h b/AmpGen/ExpressionParser.h index a89562b7fde..01c336ca3d9 100644 --- a/AmpGen/ExpressionParser.h +++ b/AmpGen/ExpressionParser.h @@ -60,8 +60,10 @@ namespace AmpGen } void add_binary( const std::string& name, binaryFCN op ) { m_binaryFunctions.emplace_back( name, op ); } - void setMPS( MinuitParameterSet* mps ) { m_mps = mps; } - static Expression Parse( const std::string& str ); + static Expression parse( const std::string& str, const MinuitParameterSet* mps=nullptr ); + static Expression parse(std::vector::const_iterator begin, + std::vector::const_iterator end , + const MinuitParameterSet* mps = nullptr ); static ExpressionParser* gExpressionParser; static ExpressionParser* getMe() { @@ -71,13 +73,12 @@ namespace AmpGen private: ExpressionParser(); - Expression processEndPoint( const std::string& name ); - Expression parseTokens( const std::vector::iterator& begin, const std::vector::iterator& end ); + Expression processEndPoint( const std::string& name, const MinuitParameterSet* mps = nullptr ); + Expression parseTokens( std::vector::const_iterator begin, std::vector::const_iterator end , const MinuitParameterSet* mps = nullptr ); void processBinaryOperators( std::vector& opCodes, std::vector& expressions ); void processUnaryOperators( std::vector& opCodes, std::vector& expressions ); - MinuitParameterSet* m_mps; std::map m_unaryFunctions; std::vector> m_binaryFunctions; }; diff --git a/AmpGen/QuarkContent.h b/AmpGen/QuarkContent.h index 17d4feb7ab7..2915d574285 100644 --- a/AmpGen/QuarkContent.h +++ b/AmpGen/QuarkContent.h @@ -28,8 +28,9 @@ namespace AmpGen QuarkState& operator-=( const QuarkState& rhs ); QuarkState operator+ ( const QuarkState& rhs ) const; QuarkState operator- ( const QuarkState& rhs ) const; - bool operator==( const QuarkState& rhs ) const; - int operator[]( const size_t& index ) const; + bool operator==( const QuarkState& rhs ) const; + bool operator!=( const QuarkState& rhs ) const; + int operator[]( const size_t& index ) const; }; class QuarkContent diff --git a/src/ExpressionParser.cpp b/src/ExpressionParser.cpp index 8758d58bcb8..6d4d9afd568 100644 --- a/src/ExpressionParser.cpp +++ b/src/ExpressionParser.cpp @@ -41,9 +41,9 @@ void ExpressionParser::processUnaryOperators( std::vector& opCodes, } } -std::vector::iterator findMatchingBracket( - const std::vector::iterator& begin, - const std::vector::iterator& end ) +std::vector::const_iterator findMatchingBracket( + std::vector::const_iterator begin, + std::vector::const_iterator end ) { int openedBrackets = 1; if( begin + 1 >= end ) return end; @@ -57,8 +57,9 @@ std::vector::iterator findMatchingBracket( return end; } -Expression ExpressionParser::parseTokens( const std::vector::iterator& begin, - const std::vector::iterator& end ) +Expression ExpressionParser::parseTokens(std::vector::const_iterator begin, + std::vector::const_iterator end, + const MinuitParameterSet* mps ) { std::vector opCodes; std::vector expressions; @@ -67,13 +68,13 @@ Expression ExpressionParser::parseTokens( const std::vector::iterat if( *it == "(" ){ auto begin_2 = it; auto end_2 = findMatchingBracket(it, end); - expressions.emplace_back( parseTokens(begin_2+1, end_2) ); + expressions.emplace_back( parseTokens(begin_2+1, end_2, mps) ); it = end_2; } else { auto f = std::find_if(m_binaryFunctions.begin(), m_binaryFunctions.end(), [it](auto& jt){ return jt.first == *it; } ); if( f != m_binaryFunctions.end() || m_unaryFunctions.count(*it) ) opCodes.push_back(*it); - else expressions.push_back( processEndPoint( *it ) ); + else expressions.push_back( processEndPoint( *it , mps ) ); } } processUnaryOperators( opCodes, expressions ); @@ -84,7 +85,7 @@ Expression ExpressionParser::parseTokens( const std::vector::iterat return expressions[0]; } -ExpressionParser::ExpressionParser() : m_mps( nullptr ) +ExpressionParser::ExpressionParser() { add_unary( "sin" ); /// "function" operator ordering is irrelevant add_unary( "cos" ); @@ -112,13 +113,22 @@ ExpressionParser::ExpressionParser() : m_mps( nullptr ) add_binary( "," , []( auto& A, auto& B ) { return ExpressionPack( A, B ); } ); } -Expression ExpressionParser::Parse( const std::string& str ) { - auto tokens = split(str, ' '); - return getMe()->parseTokens(tokens.begin(), tokens.end() ); +Expression ExpressionParser::parse( + std::vector::const_iterator begin, + std::vector::const_iterator end, + const MinuitParameterSet* mps ) { + return getMe()->parseTokens(begin, end, mps ); } +Expression ExpressionParser::parse( + const std::string& expr, + const MinuitParameterSet* mps ) { + auto tokens = split( expr , ' ' ); + return getMe()->parseTokens(tokens.cbegin(), tokens.cend() , mps ); +} + ExpressionParser* ExpressionParser::gExpressionParser = nullptr; -Expression ExpressionParser::processEndPoint( const std::string& name ) +Expression ExpressionParser::processEndPoint( const std::string& name, const MinuitParameterSet* mps ) { bool status = true; double value = lexical_cast( name, status ); @@ -128,15 +138,14 @@ Expression ExpressionParser::processEndPoint( const std::string& name ) if ( name == "e" ) return std::exp(1); if ( name == "I" ) return complex_t( 0, 1 ); if ( name == "i" ) return complex_t( 0, 1 ); - if ( m_mps != nullptr ) { - auto it = m_mps->find(name); + if ( mps != nullptr ) { + auto it = mps->find(name); if ( it != nullptr ) return MinuitParameterLink( it ); - else if ( m_mps->find(name+"_Re") != nullptr && m_mps->find(name+"_Im") != nullptr ) { - return MinuitParameterLink( m_mps->find(name+"_Re") ) + 1i * MinuitParameterLink( m_mps->find(name+"_Im") ); + else if ( mps->find(name+"_Re") != nullptr && mps->find(name+"_Im") != nullptr ) { + return MinuitParameterLink( mps->find(name+"_Re") ) + 1i * MinuitParameterLink( mps->find(name+"_Im") ); } else { - WARNING( "Token not understood: " << name << " [map size = " << m_mps->size() << "]" ); - for( auto& m : *m_mps ) INFO( m->name() ); + WARNING( "Token not understood: " << name << " [map size = " << mps->size() << "]" ); } } return Parameter( name, 0, true ); diff --git a/src/FastDT.cpp b/src/FastDT.cpp index f5dc428b2a8..a3e7eb18fcb 100644 --- a/src/FastDT.cpp +++ b/src/FastDT.cpp @@ -17,7 +17,7 @@ int FastDT::findNode( const double* event ) } FastDT::FastDT( const std::string& fname ){ - std::ifstream s(fname); + //std::ifstream s(fname); } double nnVariance(std::vector& evts, const size_t& index) diff --git a/src/FitResult.cpp b/src/FitResult.cpp index 8d09be83938..3c5253adf7c 100644 --- a/src/FitResult.cpp +++ b/src/FitResult.cpp @@ -170,8 +170,8 @@ FitResult::FitResult( const FitResult& other ) std::vector FitResult::getParameters() const { - std::vector params; - for ( auto& param : *m_mps ) params.push_back( param ); + std::vector params( m_mps->size() ); + std::copy( m_mps->begin(), m_mps->end(), params.begin() ); return params; } diff --git a/src/MinuitExpression.cpp b/src/MinuitExpression.cpp index 0988a49f595..9109155da38 100644 --- a/src/MinuitExpression.cpp +++ b/src/MinuitExpression.cpp @@ -12,10 +12,7 @@ using namespace AmpGen; MinuitExpression::MinuitExpression( const std::vector& tokens, MinuitParameterSet* mps ) { setName( tokens[0] ); - std::string total_line = ""; - for ( size_t it = 2; it != tokens.size(); ++it ) total_line += tokens[it] + " "; - ExpressionParser::getMe()->setMPS( mps ); - m_expression = ExpressionParser::Parse( total_line ); + m_expression = ExpressionParser::parse(tokens.begin() + 2 , tokens.end() , mps ); m_isGood = true; fix(); } diff --git a/src/MinuitParameterSet.cpp b/src/MinuitParameterSet.cpp index e6bfe3aaa18..6615b7b23f7 100644 --- a/src/MinuitParameterSet.cpp +++ b/src/MinuitParameterSet.cpp @@ -192,8 +192,7 @@ void MinuitParameterSet::tryAlias( const std::vector& line ) { if ( line.size() < 3 ) return; if ( line[1] == "=" ) { - std::string name = line[0]; - MinuitExpression* expr = new MinuitExpression( line, this ); + MinuitExpression* expr = new MinuitExpression(line, this ); if ( expr->isGood() ) { addToEnd( expr ); } else { diff --git a/src/Particle.cpp b/src/Particle.cpp index 020cae11406..cecc12373ce 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -337,7 +337,8 @@ std::vector> Particle::identicalDaughterOrderings() const std::vector> orderings; auto finalStateParticles = getFinalStateParticles(); std::vector zero_perm; - for( auto& particle : finalStateParticles ) zero_perm.push_back( particle->name() ); + std::transform( finalStateParticles.begin(), finalStateParticles.end(), std::back_inserter(zero_perm), + [](auto& p ){ return p->name() ; } ); std::vector indices( finalStateParticles.size() ); std::iota(indices.begin(), indices.end(), 0); do { diff --git a/src/ParticlePropertiesList.cpp b/src/ParticlePropertiesList.cpp index c3a507a2b9a..9745d94f59d 100644 --- a/src/ParticlePropertiesList.cpp +++ b/src/ParticlePropertiesList.cpp @@ -179,13 +179,13 @@ std::ostream& operator<<( std::ostream& out, const ParticlePropertiesList& ppl ) std::vector ParticlePropertiesList::getParticleNames() const { std::vector particleNames; - for ( auto& particle : m_byName ) particleNames.push_back( particle.first ); + std::transform( m_byName.begin(), m_byName.end(), std::back_inserter(particleNames), [](auto& p ) -> std::string { return p.first ; } ); return particleNames; } std::vector ParticlePropertiesList::getParticleIds() const { std::vector particleIds; - for ( auto& particle : m_byID ) particleIds.push_back( particle.first ); + std::transform( m_byID.begin(), m_byID.end(), std::back_inserter(particleIds), [](auto& p ) -> int { return p.first ; } ); return particleIds; } diff --git a/src/QuarkContent.cpp b/src/QuarkContent.cpp index d31336abae8..e34d4d1c741 100644 --- a/src/QuarkContent.cpp +++ b/src/QuarkContent.cpp @@ -100,6 +100,12 @@ bool QuarkState::operator==( const QuarkState& rhs ) const if ( rhs[i] != m_quarks[i] ) return false; return true; } + +bool QuarkState::operator!=( const QuarkState& rhs ) const +{ + return !( *this == rhs ); +} + int QuarkState::operator[]( const size_t& index ) const { return m_quarks[index]; } QuarkContent::QuarkContent() : m_quarks(1) {} @@ -185,6 +191,10 @@ std::ostream& AmpGen::operator<<( std::ostream& st, const QuarkContent& qc ) bool QuarkContent::operator==( const QuarkContent& rhs ) const { +// for ( auto& l : m_quarks ) { +// if( std::any_of( rhs.quarks().begin(), rhs.quarks().end(), [&l](auto& r){ return l == r ; } ) ) +// return true; +// } for ( auto& l : m_quarks ) { for ( auto& r : rhs.quarks() ) { if ( l == r ) return true; diff --git a/src/RecursivePhaseSpace.cpp b/src/RecursivePhaseSpace.cpp index a43657b3cb7..ce812ab3e3a 100644 --- a/src/RecursivePhaseSpace.cpp +++ b/src/RecursivePhaseSpace.cpp @@ -72,8 +72,7 @@ std::vector RecursivePhaseSpace::getFinalStates() { std::vector rt; for ( auto& f : m_nodes ) { - if ( f.decayProds == nullptr ) - rt.push_back( &f ); + if ( f.decayProds == nullptr ) rt.push_back( &f ); else { auto segs = f.decayProds->getFinalStates(); for ( auto& s : segs ) rt.push_back( s ); diff --git a/src/Simplify.cpp b/src/Simplify.cpp index aef16347bc4..fa5c0db8081 100644 --- a/src/Simplify.cpp +++ b/src/Simplify.cpp @@ -40,9 +40,10 @@ NormalOrderedExpression::Term::Term( const Expression& expression ) : std::sort( m_terms.begin(), m_terms.end(), [](auto& t1, auto& t2 ){ return t1.second > t2.second; } ) ; - // Expression t = std::accumulate( m_terms.begin(), m_terms.end(), Expression(1), std::multiplies() ); - Expression t = 1; - for( auto& f : m_terms ) t = t * f.first; + Expression t = std::accumulate( m_terms.begin(), m_terms.end(), Expression(1), [](auto& A, auto& B){ return A * B.first ; } ); + // std::multiplies() ); + //Expression t = 1; + //for( auto& f : m_terms ) t = t * f.first; m_expressionAsString = ( t / m_divisor).to_string(); } diff --git a/src/Tensor.cpp b/src/Tensor.cpp index 2eadbae90f1..3f5d6181d2d 100644 --- a/src/Tensor.cpp +++ b/src/Tensor.cpp @@ -76,8 +76,7 @@ void Tensor::append( const std::string& value ) { m_elements.emplace_back( Pa void Tensor::setupCoordinates() { - int st=1; - for( auto& d : m_dim ) st *= d; + int st = std::accumulate( m_dim.begin(), m_dim.end(), 1, std::multiplies() ); DEBUG( "Setting up coordinates: " << dimString() << " coordinate mapping = " << st ); m_symmetrisedCoordinates.resize( st ); std::iota( m_symmetrisedCoordinates.begin(), m_symmetrisedCoordinates.end(), 0 ); @@ -144,11 +143,7 @@ std::string Tensor::coordinates_to_string( const std::vector& coordinate size_t Tensor::nElements() const { - size_t dim = 1; - for ( auto& d : m_dim ) { - dim *= ( d != 0 ) ? d : 1; - } - return dim; + return std::accumulate( m_dim.begin(), m_dim.end(), 1, [](auto& dim, auto& d){ return dim * ( d == 0 ? 1 : d ) ; } ); } const std::string Tensor::dimString() const { @@ -444,13 +439,12 @@ TensorProxy AmpGen::operator*( const TensorProxy& t1, const TensorProxy& t2 ) } while ( ++i < t2_size ); Expression elementExpression = 0; - for( unsigned int i=0; isetMPS( &mps ); double pi = M_PI; - auto test = [](const std::string& expr) -> double { + auto test = [mps](const std::string& expr) -> double { std::string newLine=""; for( auto& ch : expr ){ if( ch == '(' || @@ -41,7 +40,7 @@ BOOST_AUTO_TEST_CASE( test_ExpressionParser ) { } else newLine.push_back(ch); } - return std::real( ExpressionParser::Parse(newLine)() ); }; + return std::real( ExpressionParser::parse(newLine, &mps)() ); }; BOOST_CHECK( test("a+(cos(b-sin(2/a*pi))-sin(a-cos(2*b/pi)))-b") == a+(cos(b-sin(2/a*pi))-sin(a-cos(2*b/pi)))-b ); BOOST_CHECK( test("sin(a)+sin(b)") == sin(a)+sin(b) ); diff --git a/test/test_QuarkContent.cpp b/test/test_QuarkContent.cpp new file mode 100644 index 00000000000..b48f3ad873e --- /dev/null +++ b/test/test_QuarkContent.cpp @@ -0,0 +1,24 @@ + +#define BOOST_TEST_DYN_LINK + +#define BOOST_TEST_MODULE "QuarkContent" + +#include +namespace utf = boost::unit_test; + +#include "AmpGen/QuarkContent.h" + +using namespace AmpGen; + +BOOST_AUTO_TEST_CASE( test_QuarkState ) { + + QuarkState uD("uD"); + QuarkState dU("dU"); + + BOOST_CHECK( uD != dU ); + + auto vu = uD + dU; + + BOOST_CHECK( vu.isVacuum()); + +} From 7124f9b1c218e5d7812ec3223968adafeb7fd5b4 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 27 May 2019 14:35:18 +0200 Subject: [PATCH 066/250] Fix associativity in ExpressionParser, add more tests to test_ExpressionParser --- src/ExpressionParser.cpp | 9 ++++++--- src/QuarkContent.cpp | 7 +++---- test/test_ExpressionParser.cpp | 25 ++++++++++++++++--------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/ExpressionParser.cpp b/src/ExpressionParser.cpp index 6d4d9afd568..0c541285144 100644 --- a/src/ExpressionParser.cpp +++ b/src/ExpressionParser.cpp @@ -105,8 +105,8 @@ ExpressionParser::ExpressionParser() add_binary( "^" , [](auto& A, auto& B ) { return fcn::pow(A,B); } ); add_binary( "/" , [](auto& A, auto& B ) { return A / B; } ); add_binary( "*" , [](auto& A, auto& B ) { return A * B; } ); - add_binary( "+" , [](auto& A, auto& B ) { return A + B; } ); add_binary( "-" , [](auto& A, auto& B ) { return A - B; } ); + add_binary( "+" , [](auto& A, auto& B ) { return A + B; } ); add_binary( ">" , [](auto& A, auto& B ) { return A > B; } ); add_binary( "<" , [](auto& A, auto& B ) { return A < B; } ); add_binary( "&&", []( auto& A, auto& B ) { return A && B; } ); @@ -166,9 +166,11 @@ void MinuitParameterLink::resolve( ASTResolver& resolver ) const resolver.resolve(*this); } -complex_t MinuitParameterLink::operator()() const { +complex_t MinuitParameterLink::operator()() const +{ if( m_parameter == nullptr ) ERROR("Parameter does not have end-point"); - return m_parameter->mean(); } + return m_parameter->mean(); +} ExpressionPack::ExpressionPack( const Expression& A, const Expression& B ) { @@ -183,6 +185,7 @@ ExpressionPack::ExpressionPack( const Expression& A, const Expression& B ) } else m_expressions.push_back( B ); } + std::string ExpressionPack::to_string(const ASTResolver* resolver) const { std::string rt = ""; diff --git a/src/QuarkContent.cpp b/src/QuarkContent.cpp index e34d4d1c741..ae38efea63b 100644 --- a/src/QuarkContent.cpp +++ b/src/QuarkContent.cpp @@ -191,10 +191,9 @@ std::ostream& AmpGen::operator<<( std::ostream& st, const QuarkContent& qc ) bool QuarkContent::operator==( const QuarkContent& rhs ) const { -// for ( auto& l : m_quarks ) { -// if( std::any_of( rhs.quarks().begin(), rhs.quarks().end(), [&l](auto& r){ return l == r ; } ) ) -// return true; -// } +// return std::any_of( m_quarks.begin(), m_quarks.end(), [rhs](auto& ql){ +// return std::any_of( rhs.quarks().begin(), rhs.quarks().end(), +// [ql](auto& qr){ return ql == qr; } ) ;} ); for ( auto& l : m_quarks ) { for ( auto& r : rhs.quarks() ) { if ( l == r ) return true; diff --git a/test/test_ExpressionParser.cpp b/test/test_ExpressionParser.cpp index 360636871f6..29f36b23d84 100644 --- a/test/test_ExpressionParser.cpp +++ b/test/test_ExpressionParser.cpp @@ -14,10 +14,17 @@ BOOST_AUTO_TEST_CASE( test_ExpressionParser ) { double a = 1.0; double b = 0.5; + double c = 4.0; + double d = 0.2; + double f = 3.13; + MinuitParameterSet mps( { new MinuitParameter("a",MinuitParameter::Flag::Float, a,0. ) , new MinuitParameter("b",MinuitParameter::Flag::Float, b,0. ) + , new MinuitParameter("c",MinuitParameter::Flag::Float, c, 0. ) + , new MinuitParameter("d",MinuitParameter::Flag::Float, d, 0. ) + , new MinuitParameter("f",MinuitParameter::Flag::Float, f, 0. ) }); double pi = M_PI; @@ -50,14 +57,14 @@ BOOST_AUTO_TEST_CASE( test_ExpressionParser ) { BOOST_CHECK( test("(b+a/b) * (a-b/a)") == (b+a/b) * (a-b/a) ); BOOST_CHECK( test("(0.1*a+1)*a+1.1-sin(a)-log(a)/a*3/4") == (0.1*a+1)*a+1.1-sin(a)-log(a)/a*3/4 ); BOOST_CHECK( test("sin(2 * a) + cos(pi / b)") == sin(2 * a) + cos(pi / b) ); -// BOOST_CHECK( test("1 - sin(2 * a) + cos(pi / b)") == -// BOOST_CHECK( test("sqrt(1 - sin(2 * a) + cos(pi / b) / 3)") == -// BOOST_CHECK( test("(a^2 / sin(2 * pi / b)) -a / 2") == -// BOOST_CHECK( test("1-(a/b*0.5)") == -// BOOST_CHECK( test("e^log(7*a)") == -// BOOST_CHECK( test("10^log(3+b)") == -// BOOST_CHECK( test("(cos(2.41)/b)") == -// BOOST_CHECK( test("-(sin(pi+a)+1)") == -// BOOST_CHECK( test("a-(e^(log(7+b)))") == + BOOST_CHECK( test("a - ( b + c ) " ) == a - ( b + c ) ); + BOOST_CHECK( test("a - b + c - d / b + f - a " ) == a - b + c - d / b + f -a ); + BOOST_CHECK( test("1 + 2 * 3" ) == 1 + 2 * 3 ); + BOOST_CHECK( test("4 + 2 " ) == 6 ); + BOOST_CHECK( test("3 * 6 - 7 + 2 " ) == 3 * 6 - 7 + 2 ); + BOOST_CHECK( test("6 * 2 + ( 5 - 3 ) * 3 - 8 " ) == 6 * 2 + ( 5 - 3)*3 -8 ); + BOOST_CHECK( test("( 3 + 4 ) + 7 * 2 - 1 - 9 " ) == 3 + 4 + 7 * 2 - 1 - 9); + BOOST_CHECK( test("5 - 2 + 4 * ( 8 - ( 5 + 1 ) ) + 9 " ) == 5 - 2 + 4 *( 8 - (5+1)) +9 ); + BOOST_CHECK( test("( 8 - 1 + 3 ) * 6 - ( ( 3 + 7 ) * 2 )" ) == (8-1+3)*6 - ((3+7)*2) ); } From d56fb880300f35f5bd0a025b692006e47395dd69 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 27 May 2019 15:08:28 +0200 Subject: [PATCH 067/250] Fix example in Particle.h, improve README.md to reflect improvements in parameter expressions --- AmpGen/Particle.h | 9 +++++---- README.md | 5 +++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/AmpGen/Particle.h b/AmpGen/Particle.h index 44a6bb892eb..02e68812ce7 100644 --- a/AmpGen/Particle.h +++ b/AmpGen/Particle.h @@ -61,18 +61,19 @@ namespace AmpGen These will be denoted by the use of [] braces, so for example \code{cpp} - Delta(1232)++{p+,pi+} - Delta(1232)++[D]{p+,pi+} + a(1)(1260)+{rho(770)0,pi+} + a(1)(1260)+[D]{rho(770)0,pi+} \endcode - correspond to the S-wave and D-wave decays of the @f$\Delta(1232)^{++}@f$ baryon. + correspond to the S-wave and D-wave decays of the @f$a(1)(1260)^{+}@f$ meson. As a rule, the lowest orbital state permitted by the relevant conservation laws of the decay is used if the orbital state is not specified, so the conservation of angular momentum, and the conservation of parity if the decay proceeds via the strong or electromagnetic force. The modifier syntax is also used to specify a different choice of lineshape for the resonance. For example, a common parameterisation for the @f$\rho(770)@f$ meson is the Gounaris-Sakurai propagator, - which accounts for dispersive corrections to the @f$I=1@f$ dipion scattering. In this example + which accounts for dispersive corrections to the @f$I=1@f$ dipion system. + In this example \code{cpp} rho(770)0[GounarisSakurai]{pi+,pi-} diff --git a/README.md b/README.md index 5ed2a882ed8..0ad406aab5a 100644 --- a/README.md +++ b/README.md @@ -255,14 +255,15 @@ For example, if we wished to vary the K(1)(1270)+ mass in the above example, but K(1)(1270)+_mass 0 1.27 0.01 0.0 2.0 ``` -(Scalar) parameters can also be related to each other via simple expressions, although the implementation of this is rather unreliable so should be used with caution. +(Scalar) parameters can also be related to each other via expressions. Suppose for example we have K(1)(1270)+ and K(1)(1270)bar- in the same fit (for example, for D-\>KKpipi) The properties of one can be allowed to vary, for example the K(1)(1270)+, and the other fixed to the same value, using: ``` K(1)(1270)+_mass 0 1.27 0.01 0.0 2.0 K(1)(1270)bar-_mass = K(1)(1270)+_mass ``` -Due to the abundance of **odd** glyphs such as brackets and +/- in parameter names, parameter expressions are white space delimited and somewhat sensitive to bracket usage. +Parameter expressions are whitespace delimited due to the abundance of **odd** glyphs such as brackets and +/- in the names of parameters. +Expressions support the binary operations (+,-,/,*,^), as well as common unary functions such as sqrt, trigonometric functions etc. ### Spin Formalisms From 6a00706b3de11c77c626ec967849dbc360a83869 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 28 May 2019 17:09:36 +0200 Subject: [PATCH 068/250] Changes from code review --- AmpGen/DalitzIntegrator.h | 26 +++++----- AmpGen/ErrorPropagator.h | 87 +++++----------------------------- AmpGen/FitResult.h | 14 +++--- AmpGen/Lineshapes.h | 11 +---- AmpGen/OptionsParser.h | 6 ++- AmpGen/Plots.h | 5 +- src/DalitzIntegrator.cpp | 7 ++- src/ErrorPropagator.cpp | 45 ++++++++++++++++-- src/Lineshapes/AxialKaon.cpp | 62 ------------------------ src/Lineshapes/BW.cpp | 17 ++++--- src/Lineshapes/ObelixRho.cpp | 92 ------------------------------------ src/Lineshapes/kMatrix.cpp | 1 + src/OptionsParser.cpp | 9 ++-- src/Pade.cpp | 0 src/Spline.cpp | 2 +- 15 files changed, 102 insertions(+), 282 deletions(-) delete mode 100644 src/Lineshapes/AxialKaon.cpp delete mode 100644 src/Lineshapes/ObelixRho.cpp delete mode 100644 src/Pade.cpp diff --git a/AmpGen/DalitzIntegrator.h b/AmpGen/DalitzIntegrator.h index 31c09622e26..06bbdb144df 100644 --- a/AmpGen/DalitzIntegrator.h +++ b/AmpGen/DalitzIntegrator.h @@ -32,18 +32,8 @@ namespace AmpGen DalitzIntegrator( const double& s0, const double& s1, const double& s2, const double& s3); - template - double integrate( FCN fcn, const double& s) const - { - double event[12]; - for(size_t i = 0; i < 12; ++i) event[i] = 0; - TF2 f( "fcn", [&]( double* x, double* p ) { - sqCo pos = {x[0], x[1]}; - setEvent( pos, event, s); - return J(pos, s) * std::real( fcn(event) ); }, 0, 1, 0, 1, 0 ); - return integrate_internal(f) / s; - } - + template double integrate( FCN fcn, const double& s) const; + template double integrate( FCN fcn ) const { return integrate( fcn, m_s0 ); @@ -80,6 +70,18 @@ namespace AmpGen double integrate_internal( TF2& fcn ) const ; }; + template + double DalitzIntegrator::integrate( FCN fcn, const double& s) const + { + double event[12]; + for(size_t i = 0; i < 12; ++i) event[i] = 0; + TF2 f( "fcn", [&]( double* x, double* p ) { + sqCo pos = {x[0], x[1]}; + setEvent( pos, event, s); + return J(pos, s) * std::real( fcn(event) ); }, 0, 1, 0, 1, 0 ); + return integrate_internal(f) / s; + } + } // namespace AmpGen #endif diff --git a/AmpGen/ErrorPropagator.h b/AmpGen/ErrorPropagator.h index 7470162c0dc..8a73df91f8b 100644 --- a/AmpGen/ErrorPropagator.h +++ b/AmpGen/ErrorPropagator.h @@ -27,13 +27,13 @@ class TRandom3; namespace AmpGen { class MinuitParameterSet; - /// \class LinearErrorPropagator - /// Propagates uncertainties on functors using either a MinuitParameterSet (thus assuming a diagonal covariance matrix) - /// or with a set of parameters and a covariance matrix (i.e. the product of a fit). - /// Can be used for calculating the uncertainties on observables such as Fit fractions, - /// or for producing uncertainty bands in predictions on figures. - /// Usage is - + /** @class LinearErrorPropagator + Propagates uncertainties on functors using either a MinuitParameterSet (thus assuming a diagonal covariance matrix) + or with a set of parameters and a covariance matrix (i.e. the product of a fit). + Can be used for calculating the uncertainties on observables such as Fit fractions, + or for producing uncertainty bands in predictions on figures. + Usage is + */ class LinearErrorPropagator { public: @@ -41,85 +41,20 @@ namespace AmpGen LinearErrorPropagator( const std::vector& params ); ///< Constructor for LinearErrorPropagator, taking a MinuitParameterSet as argument, assumes a diagonal coviarance matrix using the uncertainties on parameters. LinearErrorPropagator( const MinuitParameterSet& params ); - ///< Constructor for LinearErrorPropagator, taking a covariance matrix and a vector parameters - LinearErrorPropagator( const TMatrixD& reducedCovarianceMatrix, - const std::vector& params ); + LinearErrorPropagator( const TMatrixD& reducedCovarianceMatrix, const std::vector& params ); ///< Calculates the uncertainty on functor fcn. template double operator()( FCN fcn ) const { - return getError( fcn ); + return getError( std::function(fcn) ); } ///< Calculates the error on functor fcn (should take no arguments and return a double). - template double getError( FCN fcn ) const - { - unsigned int N = m_cov.GetNrows(); - TVectorD errorVec( N ); - for ( unsigned int i = 0; i < N; ++i ) { - DEBUG( "Perturbing parameter: [" << m_parameters[i]->name() << "] " << startingValue << " by " - << sqrt( m_cov( i, i ) ) << " " << m_parameters[i] ); - errorVec(i) = derivative(fcn,i); - fcn(); - } - return sqrt( errorVec * ( m_cov * errorVec ) ); - } - - ///< Calculate the uncertainties on a functor that returns an array of doubles of size RANK, used for propagating the uncertainties on figures. - template std::array getVectorError( FCN fcn ) const - { - unsigned int N = m_cov.GetNrows(); - std::array errorVec; - for ( unsigned int i = 0; i < RANK; ++i ) errorVec[i].ResizeTo( N ); - for ( unsigned int i = 0; i < N; ++i ) { - double startingValue = m_parameters[i]->mean(); - double error = sqrt( m_cov( i, i ) ); - double min = m_parameters[i]->mean() - error; - double max = m_parameters[i]->mean() + error; - DEBUG( "Perturbing parameter: " << m_parameters[i]->name() << " -> [" << min << ", " << max << "]" ); - - m_parameters[i]->setCurrentFitVal( max ); - auto plus_variation = fcn(); - m_parameters[i]->setCurrentFitVal( min ); - auto minus_variation = fcn(); - m_parameters[i]->setCurrentFitVal( startingValue ); - for ( size_t j = 0; j < RANK; ++j ) { - errorVec[j]( i ) = ( plus_variation[j] - minus_variation[j] ) / ( 2 * error ); - } - } - fcn(); - std::array rt; - for ( unsigned int j = 0; j < RANK; ++j ) rt[j] = sqrt( errorVec[j] * ( m_cov * errorVec[j] ) ); - return rt; - } + double getError( const std::function& fcn ) const; ///< Calculate the uncertainties on a functor that returns a vector of size RANK. - template std::vector getVectorError( FCN fcn, size_t RANK ) const - { - unsigned int N = m_cov.GetNrows(); - std::vector errorVec( RANK, TVectorD( N ) ); - for ( unsigned int i = 0; i < N; ++i ) { - double startingValue = m_parameters[i]->mean(); - double error = sqrt( m_cov( i, i ) ); - double min = m_parameters[i]->mean() - error; - double max = m_parameters[i]->mean() + error; - DEBUG( "Perturbing parameter: " << m_parameters[i]->name() << " -> [" << min << ", " << max << "]" ); - - m_parameters[i]->setCurrentFitVal( max ); - auto plus_variation = fcn(); - m_parameters[i]->setCurrentFitVal( min ); - auto minus_variation = fcn(); - m_parameters[i]->setCurrentFitVal( startingValue ); - for ( size_t j = 0; j < RANK; ++j ) { - errorVec[j]( i ) = ( plus_variation[j] - minus_variation[j] ) / ( 2 * error ); - } - } - fcn(); - std::vector rt( RANK, 0 ); - for ( unsigned int j = 0; j < RANK; ++j ) rt[j] = sqrt( errorVec[j] * ( m_cov * errorVec[j] ) ); - return rt; - } + std::vector getVectorError( const std::function(void)>& fcn, size_t RANK ) const; /// Calculate the variance-covariance matrix of functor set functions. std::vector combinationWeights( const std::vector>& functions ); diff --git a/AmpGen/FitResult.h b/AmpGen/FitResult.h index 3098a44d8c8..e16103e7798 100644 --- a/AmpGen/FitResult.h +++ b/AmpGen/FitResult.h @@ -16,17 +16,17 @@ namespace AmpGen class FitResult { private: - double m_chi2; - double m_LL; - double m_nBins; - double m_nParam; - int m_status; + double m_chi2 = {0}; + double m_LL = {-999}; + double m_nBins = {0}; + double m_nParam = {0}; + int m_status = {-1}; + bool m_fitted = {false}; EventType m_eventType; std::map m_observables; std::vector m_fitFractions; TMatrixD m_covarianceMatrix; std::shared_ptr m_mps; - bool m_fitted; std::map m_covMapping; std::string getLastLine( std::ifstream& in ) const; @@ -42,7 +42,7 @@ namespace AmpGen FitResult( const MinuitParameterSet& mps, const TMatrixD& covMini ); FitResult( const std::string& filename, const EventType& evtType = EventType() ); - FitResult() : m_chi2( 0 ), m_LL( -999 ), m_nBins( 0 ), m_nParam( 0 ), m_status( -1 ), m_fitted( 0 ) {} + FitResult() = default; bool readFile( const std::string& fname ); void writeToFile( const std::string& fname ); diff --git a/AmpGen/Lineshapes.h b/AmpGen/Lineshapes.h index 602f68bb352..0ad6b22634c 100644 --- a/AmpGen/Lineshapes.h +++ b/AmpGen/Lineshapes.h @@ -314,6 +314,7 @@ namespace AmpGen * @brief Polynominal shape \f$ \mathcal{A}(s) = \sum^n_i c_i s^{i} \f$ where the sum is to lineshapeModifier::Degree, and the free parameters of the shape are lineshapeModifier_ci */ DECLARE_LINESHAPE( Poly ); + /** @ingroup Lineshapes class FOCUS * @brief K matrix amplitudes used for I=1/2 and I=3/2 in the description of the \f$ K\pi \f$ S-wave in the analysis of @f$ D^{+}\rightarrow K^{-}\pi^{+}\pi^{+}@f$ https://arxiv.org/abs/0705.2248 */ @@ -322,16 +323,6 @@ namespace AmpGen /// I=1/2 and I=3/2 K Matrices used in the description of the \f$ K\pi\f$ S-wave in the analysis of @f$\eta_{c}\rightarrow K^{+} K^{-} \pi^{0}@f$ https://arxiv.org/abs/1701.04881 DECLARE_LINESHAPE( PALANO ); - /** @ingroup Lineshapes class ObelixRho - @brief Amplitude to describe the vector-isovector system, otherwise known as the @f$ \rho @f$ mesons. WARNING untested. - - Vector-Isovector amplitude @f$(I=1, J=1)@f$ using a K-matrix to describe the @f$\pi\pi, KK, \pi\pi\pi\pi @f$ channels using three poles, commonly associated with - the @f$ \rho(770), \rho(1450), \rho(1900) @f$ resonances.*/ - DECLARE_LINESHAPE( ObelixRho ); - - /// K matrix to describe \f$K_1(1270) / K_1(1400)\f$. WARNING incompleted. - DECLARE_LINESHAPE( AxialKaon ); - /** @ingroup Lineshapes class kMatrixSimple @brief Simple and flexible K matrix that implements a variable number of scalar channels and poles. Flexible K matrix implementation that accepts a variable number of scalar channels and pole terms. diff --git a/AmpGen/OptionsParser.h b/AmpGen/OptionsParser.h index 21f4cbcef53..8bf2a2ca12a 100644 --- a/AmpGen/OptionsParser.h +++ b/AmpGen/OptionsParser.h @@ -19,6 +19,7 @@ namespace AmpGen static bool printHelp(); static void setArgs( int argc, char** argv, const std::string& description="" ); static void setArg( const std::string& arg ); + void setQuiet(); void addArg( const std::string& arg ); void setCommandLineArgs( int argc, char** argv, const std::string& description =""); void import( const std::string& fName ); @@ -30,10 +31,11 @@ namespace AmpGen private: std::map> m_parsedLines; - bool m_printHelp; + bool m_printHelp = {false}; + bool m_quiet = {false}; static OptionsParser* gOptionsParser; - OptionsParser(); + OptionsParser() = default; bool ignoreThisLine( const std::string& line ); void readStream( std::istream& is ); std::vector makeParsedStrings( const std::string& line, int& braceDepth ) const; diff --git a/AmpGen/Plots.h b/AmpGen/Plots.h index 3994d21ff9c..d5d62e43548 100644 --- a/AmpGen/Plots.h +++ b/AmpGen/Plots.h @@ -65,11 +65,10 @@ namespace AmpGen TH1D* plot = projection.plot(); plot->SetName( ( prefix + plot->GetName() ).c_str() ); auto normalisations = getNorms( fcn, bid ); - auto vectorBinFunctor = [&normalisations, &fcn, &bid] { fcn.transferParameters(); bid.update( fcn, normalisations ); - std::array values; + std::vector values(NBINS); double total = 0; for ( size_t bin = 0; bin < NBINS; ++bin ) { values[bin] = fcn.norm( normalisations[bin] ); @@ -79,7 +78,7 @@ namespace AmpGen return values; }; auto values = vectorBinFunctor(); - auto errors = linProp.getVectorError( vectorBinFunctor ); + auto errors = linProp.getVectorError( vectorBinFunctor, NBINS ); for ( size_t bin = 0; bin < NBINS; ++bin ) { plot->SetBinContent( bin + 1, values[bin] ); plot->SetBinError( bin + 1, errors[bin] ); diff --git a/src/DalitzIntegrator.cpp b/src/DalitzIntegrator.cpp index 6c7d7ac02fb..320ce538c70 100644 --- a/src/DalitzIntegrator.cpp +++ b/src/DalitzIntegrator.cpp @@ -38,7 +38,12 @@ double DalitzIntegrator::sqDp1( const Event& evt ) const TLorentzVector p2( ( evt.address( 4 ) ) ); TLorentzVector p3( ( evt.address( 8 ) ) ); TLorentzVector pA = p1 + p2; - return acos( 2 * ( pA.Mag() - m_min ) / ( m_max - m_min ) - 1 ) / M_PI; + auto arg = 2 * ( pA.Mag() - m_min ) / ( m_max - m_min ) - 1; + if( arg > 1 || arg < -1 ){ + ERROR("Argument: " << arg << " is out-of-bounds"); + return -1; + } + return acos(arg)/M_PI; } double DalitzIntegrator::sqDp2( const Event& evt ) const { diff --git a/src/ErrorPropagator.cpp b/src/ErrorPropagator.cpp index 38cf12fb436..47da3e8d449 100644 --- a/src/ErrorPropagator.cpp +++ b/src/ErrorPropagator.cpp @@ -82,11 +82,9 @@ LinearErrorPropagator::LinearErrorPropagator( const MinuitParameterSet& mps ) void LinearErrorPropagator::add( const LinearErrorPropagator& p2 ) { - size_t superSet = size(); size_t oldSize = size(); auto p1_pMap = posMap(); - std::vector props( p2.size() ); for ( size_t x = 0; x != p2.size(); ++x ) { auto it = p1_pMap.find( p2.params()[x]->name() ); @@ -96,14 +94,11 @@ void LinearErrorPropagator::add( const LinearErrorPropagator& p2 ) } else props[x] = it->second; } - TMatrixD old_cov = m_cov; if ( superSet != oldSize ) m_cov.ResizeTo( superSet, superSet ); - for ( size_t x = 0; x != oldSize; ++x ) { for ( size_t y = 0; y != oldSize; ++y ) m_cov( x, y ) = old_cov( x, y ); } - auto p2_cov = p2.cov(); for ( size_t x = 0; x < p2.size(); ++x ) { for ( size_t y = 0; y < p2.size(); ++y ) { @@ -114,6 +109,46 @@ void LinearErrorPropagator::add( const LinearErrorPropagator& p2 ) } } +double LinearErrorPropagator::getError( const std::function& fcn ) const +{ + unsigned int N = m_cov.GetNrows(); + TVectorD errorVec( N ); + for ( unsigned int i = 0; i < N; ++i ) { + DEBUG( "Perturbing parameter: [" << m_parameters[i]->name() << "] " << startingValue << " by " + << sqrt( m_cov( i, i ) ) << " " << m_parameters[i] ); + errorVec(i) = derivative(fcn,i); + fcn(); + } + return sqrt( errorVec * ( m_cov * errorVec ) ); +} + +std::vector LinearErrorPropagator::getVectorError( const std::function(void)>& fcn, size_t RANK ) const +{ + unsigned int N = m_cov.GetNrows(); + std::vector errorVec( RANK, TVectorD( N ) ); + for ( unsigned int i = 0; i < N; ++i ) { + double startingValue = m_parameters[i]->mean(); + double error = sqrt( m_cov( i, i ) ); + double min = m_parameters[i]->mean() - error; + double max = m_parameters[i]->mean() + error; + DEBUG( "Perturbing parameter: " << m_parameters[i]->name() << " -> [" << min << ", " << max << "]" ); + + m_parameters[i]->setCurrentFitVal( max ); + auto plus_variation = fcn(); + m_parameters[i]->setCurrentFitVal( min ); + auto minus_variation = fcn(); + m_parameters[i]->setCurrentFitVal( startingValue ); + for ( size_t j = 0; j < RANK; ++j ) { + errorVec[j]( i ) = ( plus_variation[j] - minus_variation[j] ) / ( 2 * error ); + } + } + fcn(); + std::vector rt( RANK, 0 ); + for ( unsigned int j = 0; j < RANK; ++j ) rt[j] = sqrt( errorVec[j] * ( m_cov * errorVec[j] ) ); + return rt; +} + + void LinearErrorPropagator::reset() { for ( int x = 0; x < m_cov.GetNrows(); ++x ) { diff --git a/src/Lineshapes/AxialKaon.cpp b/src/Lineshapes/AxialKaon.cpp deleted file mode 100644 index eebc035edc6..00000000000 --- a/src/Lineshapes/AxialKaon.cpp +++ /dev/null @@ -1,62 +0,0 @@ - -#include -#include -#include - -#include "AmpGen/Lineshapes.h" -#include "AmpGen/kMatrix.h" -#include "AmpGen/Spline.h" -#include "AmpGen/Expression.h" -#include "AmpGen/Factory.h" -#include "AmpGen/Tensor.h" -#include "AmpGen/Utilities.h" - -using namespace AmpGen; - -DEFINE_LINESHAPE( AxialKaon ) -{ - ERROR("This lineshape does not work as intended, should not be used"); -/* - - Spline rho_Krho("rho_Krho",20, 0.597247, 5, - {5.35636e-23, 0.000210696, 0.00208479, 0.00993997, 0.0415061, 0.120885, 0.196599, 0.256062, 0.304949, 0.34693, 0.384132, 0.417868, 0.448995, 0.478101, 0.505606, 0.531815, 0.556963, 0.581226, 0.604745, 0.627631}); - - Spline rho_Kstpi("rho_Kspi",20,0.597247, 5, - {6.29163e-23, 0.000390208, 0.0161092, 0.0855491, 0.128145, 0.159565, 0.184867, 0.20627, 0.224985, 0.241753, 0.257056, 0.271229, 0.284507, 0.297066, 0.309035, 0.320516, 0.331588, 0.342313, 0.35274, 0.362912} ); - - Spline rho_KstpiD("rho_KspiD",20,0.597247, 5, - {6.29163e-23, 0.000390208, 0.0161092, 0.0855491, 0.128145, 0.159565, 0.184867, 0.20627, 0.224985, 0.241753, 0.257056, 0.271229, 0.284507, 0.297066, 0.309035, 0.320516, 0.331588, 0.342313, 0.35274, 0.362912} ); - - Spline rho_KSpi("rho_KSpi",20,0.597247, 5, - {5.58343e-23, 0.000178087, 0.00132915, 0.00423057, 0.00963868, 0.0185276, 0.0324146, 0.053891, 0.0870863, 0.13619, 0.202066, 0.282239, 0.373053, 0.470919, 0.572771, 0.67618, 0.779316, 0.880855, 0.979877, 1.07577}); - - - std::vector phaseSpace = { rho_Krho(s), rho_Kstpi(s), rho_KstpiD(s), rho_KSpi(s) }; - - std::vector< std::string > channels = {"Krho","Kspi","KspiD","KSpi"}; - unsigned int nPoles = 2; - std::vector poleConfigs; - for( unsigned int pole=1;pole <= nPoles; ++pole ) - { - std::string stub = "AxialKaon_p"+std::to_string(pole)+"_"; - Expression mass = Parameter( stub + "mass" ); - poleConfig p( mass * mass ); - for ( unsigned int ch = 0; ch < 4; ++ch ) p.add( Parameter( stub + channels[ch] ) ); - poleConfigs.push_back( p ); - } - auto kMatrix = constructKMatrix( s, 4, poleConfigs ); - - Tensor F = getPropagator( kMatrix, phaseSpace ); - - auto tokens = split( lineshapeModifier, '.' ); - unsigned int pTerm = stoi(tokens[0]); - unsigned int channel = stoi(tokens[1]); - auto pole = poleConfigs[pTerm]; - Expression M = 0; - for ( unsigned int i = 0; i < pole.couplings.size(); ++i ) { - M = M + F[{channel, i}] * pole.couplings[i]; - } - return SubTree( M / ( pole.s - s ) ); - */ - return 0; -} diff --git a/src/Lineshapes/BW.cpp b/src/Lineshapes/BW.cpp index 6f8e8b8c417..5f771cdc901 100644 --- a/src/Lineshapes/BW.cpp +++ b/src/Lineshapes/BW.cpp @@ -15,17 +15,19 @@ DEFINE_LINESHAPE( FormFactor ) { auto props = ParticlePropertiesList::get( particleName ); Expression radius = Parameter( particleName + "_radius", props->radius() ); - + Expression mass = Parameter( particleName + "_mass" , props->mass() ); const Expression q2 = make_cse( Q2( s, s1, s2 ) ); + const Expression q20 = make_cse( Q2( mass*mass, s1, s2 ) ); int Lp = L; if( lineshapeModifier == "L0" ) Lp = 0; if( lineshapeModifier == "L1" ) Lp = 1; if( lineshapeModifier == "L2" ) Lp = 2; if( lineshapeModifier == "L3" ) Lp = 3; - const Expression FormFactor = lineshapeModifier.find("BL") == std::string::npos ? - sqrt( BlattWeisskopf_Norm( q2 * radius * radius, 0, Lp ) ) : - sqrt( BlattWeisskopf(q2*radius*radius, Lp ) ); + Expression FormFactor = sqrt( BlattWeisskopf_Norm( q2 * radius * radius, 0, Lp ) ); + if ( lineshapeModifier == "BL" ) FormFactor = sqrt( BlattWeisskopf( q2 * radius * radius, Lp ) ); + if ( lineshapeModifier == "BELLE2018" ) FormFactor = sqrt( BlattWeisskopf_Norm( q2 * radius * radius, q20 * radius * radius, Lp ) ); + if( L != 0 ){ ADD_DEBUG( q2 , dbexpressions ); ADD_DEBUG( radius , dbexpressions ); @@ -62,8 +64,9 @@ DEFINE_LINESHAPE( BW ) const Expression& radius = Parameter( particleName + "_radius", props->radius() ); const Expression q2 = make_cse( Abs(Q2( s_cse, s1, s2 ) ) ) ; const Expression q20 = make_cse( Abs(Q2( mass * mass, s1, s2 )) ); - Expression FormFactor = sqrt( BlattWeisskopf_Norm( q2 * radius * radius, 0, L ) ); - if ( lineshapeModifier == "BL" ) FormFactor = sqrt( BlattWeisskopf( q2 * radius * radius, L ) ); + Expression FormFactor = sqrt( BlattWeisskopf_Norm( q2 * radius * radius, 0, L ) ); + if ( lineshapeModifier == "BL" ) FormFactor = sqrt( BlattWeisskopf( q2 * radius * radius, L ) ); + if ( lineshapeModifier == "BELLE2018" ) FormFactor = sqrt( BlattWeisskopf_Norm( q2 * radius * radius, q20 * radius * radius, L ) ); Expression runningWidth = width( s_cse, s1, s2, mass, width0, radius, L, dbexpressions ); const Expression BW = FormFactor / ( mass * mass - s_cse -1i * mass * runningWidth ); const Expression kf = kFactor( mass, width0, dbexpressions ); @@ -71,7 +74,7 @@ DEFINE_LINESHAPE( BW ) ADD_DEBUG( runningWidth, dbexpressions ); ADD_DEBUG( BW, dbexpressions ); ADD_DEBUG( kf, dbexpressions ); - return kf * BW; + return lineshapeModifier == "BELLE2018" ? BW : kf*BW; } DEFINE_LINESHAPE( SBW ) diff --git a/src/Lineshapes/ObelixRho.cpp b/src/Lineshapes/ObelixRho.cpp deleted file mode 100644 index 238f076cc42..00000000000 --- a/src/Lineshapes/ObelixRho.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include -#include -#include -#include - -#include "AmpGen/Expression.h" -#include "AmpGen/Factory.h" -#include "AmpGen/Lineshapes.h" -#include "AmpGen/MsgService.h" -#include "AmpGen/ParticleProperties.h" -#include "AmpGen/Tensor.h" -#include "AmpGen/Utilities.h" - -using namespace AmpGen; - -#include "AmpGen/ParticlePropertiesList.h" -#include "AmpGen/kMatrix.h" - -DEFINE_LINESHAPE( ObelixRho ) -{ - Expression sInGeV = SubTree( s / (GeV*GeV) ); - DEBUG( "kMatrix modifier " << lineshapeModifier << " particle = " << particleName ); - auto tokens = split( lineshapeModifier, '.' ); - - DEBUG( "kMatrix modifier = " << lineshapeModifier << " nTokens = " << tokens.size() ); - unsigned int pTerm = tokens.size() > 0 ? stoi( tokens[0] ) : 999; - if ( pTerm == 999 ) { - ERROR( "Pole term not recognised: " << pTerm ); - } - - double mPiPlus( 0.139570 ); - double mKPlus( 0.493677 ); - std::vector phaseSpace = {phsp_twoBody( sInGeV, mPiPlus, mPiPlus ), phsp_fourPi( sInGeV ), - phsp_twoBody( sInGeV, mKPlus, mKPlus )}; - const unsigned int nPoles = 3; - const unsigned int nChannels = 3; - auto props = ParticlePropertiesList::get( "rho(770)0" ); - - const Expression radius = Parameter( particleName + "_radius", props->radius() ); - - std::vector poleConfigs; - - for ( unsigned int i = 1; i <= nPoles; ++i ) { - std::string stub = "rho_p" + std::to_string( i ); - Expression mRho = Parameter( ( stub + "_mass" ) ); - Expression gRho1 = Parameter( ( stub + "_pipi" ) ); - Expression gRho2 = Parameter( ( stub + "_4pi" ) ); - Expression gRho3 = Parameter( ( stub + "_KK" ) ); - poleConfig pole( mRho * mRho ); - - pole.add( gFromGamma( mRho, gRho1, phsp_twoBody( mRho * mRho, mPiPlus, mPiPlus ) ), - BL( sInGeV, mRho * mRho, mPiPlus * mPiPlus, mPiPlus * mPiPlus, radius, 1 ) ); - - pole.add( gFromGamma( mRho, gRho2, phsp_fourPi( mRho * mRho ) ) ); - - pole.add( gFromGamma( mRho, gRho3, phsp_twoBody( mRho * mRho, mKPlus, mKPlus ) ), - BL( sInGeV, mRho * mRho, mKPlus * mKPlus, mKPlus * mKPlus, radius, 1 ) ); - - poleConfigs.emplace_back( pole ); - } - - auto kMatrix = constructKMatrix( sInGeV, nChannels, poleConfigs ); - - if ( dbexpressions != nullptr ) { - for ( auto& p : poleConfigs ) { - ADD_DEBUG( p.s, dbexpressions ); - ADD_DEBUG( p.couplings[0], dbexpressions ); - ADD_DEBUG( p.couplings[1], dbexpressions ); - ADD_DEBUG( p.couplings[2], dbexpressions ); - } - ADD_DEBUG( phaseSpace[0], dbexpressions ); - ADD_DEBUG( phaseSpace[1], dbexpressions ); - ADD_DEBUG( phaseSpace[2], dbexpressions ); - for ( unsigned int i = 0; i < nChannels; ++i ) { - for ( unsigned int j = 0; j < nChannels; ++j ) { - dbexpressions->emplace_back( "K[" + std::to_string( i ) + "," + std::to_string( j ) + "]", kMatrix[{i, j}] ); - } - } - } - - Tensor propagator = getPropagator( kMatrix, phaseSpace ); - - Expression M; - - auto pole = poleConfigs[pTerm]; - const Expression q2 = Abs( Q2( s, s1, s2 ) ); - - for ( unsigned int i = 0; i < nChannels; ++i ) { - M = M + propagator[{0, i}] * pole.g( i ); - } - return SubTree( M / ( pole.s - sInGeV ) ); -} diff --git a/src/Lineshapes/kMatrix.cpp b/src/Lineshapes/kMatrix.cpp index 86db4312e06..f6063bead25 100644 --- a/src/Lineshapes/kMatrix.cpp +++ b/src/Lineshapes/kMatrix.cpp @@ -24,6 +24,7 @@ Expression AmpGen::phsp_twoBody( const Expression& s, const double& m0, const do Expression AmpGen::phsp_fourPi( const Expression& s ) { + // Parameterisation of the 4pi phase-space taken from Laura++ (https://laura.hepforge.org/ or Ref. https://arxiv.org/abs/1711.09854) double mPiPlus( 0.139570 ); Expression rho_4pi = pol( s, {0.00051, -0.01933, 0.13851, -0.20840, -0.29744, 0.13655, 1.07885} ); return Ternary( s > 1, phsp_twoBody( s, 2 * mPiPlus, 2 * mPiPlus ), rho_4pi ); diff --git a/src/OptionsParser.cpp b/src/OptionsParser.cpp index 08e27e94eb2..789d8c0ee62 100644 --- a/src/OptionsParser.cpp +++ b/src/OptionsParser.cpp @@ -10,8 +10,6 @@ using namespace AmpGen; -OptionsParser::OptionsParser() : m_printHelp(false) {} - OptionsParser* OptionsParser::gOptionsParser = nullptr; OptionsParser* OptionsParser::getMe() @@ -20,6 +18,9 @@ OptionsParser* OptionsParser::getMe() return gOptionsParser; } +void OptionsParser::setQuiet(){ + m_quiet = true; +} bool OptionsParser::ignoreThisLine( const std::string& line ) { @@ -33,7 +34,7 @@ bool OptionsParser::ignoreThisLine( const std::string& line ) void OptionsParser::setCommandLineArgs( int argc, char** argv, const std::string& description ) { - printSplash(); + if( !m_quiet ) printSplash(); int x = 0; while ( ++x < argc ) { std::string token = std::string( argv[x] ); @@ -67,7 +68,7 @@ void OptionsParser::setCommandLineArgs( int argc, char** argv, const std::string void OptionsParser::import( const std::string& fName ) { - INFO( "Importing: " << fName ); + if( !m_quiet) INFO( "Importing: " << fName ); if ( !fileExists( fName ) ) { ERROR( "Cannot find file: " << fName ); return; diff --git a/src/Pade.cpp b/src/Pade.cpp deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/Spline.cpp b/src/Spline.cpp index 6efb89eb628..e85f614cea3 100644 --- a/src/Spline.cpp +++ b/src/Spline.cpp @@ -100,7 +100,7 @@ SplineTransfer::SplineTransfer( const unsigned int& address, const unsigned int& { unsigned int size = N - 2; - TMatrixD M( N - 2, N - 2 ); + TMatrixD M(size, size); for ( unsigned int i = 0; i < size; ++i ) { M[i][i] = 4; if ( i != size - 1 ) { From 5f9022982dc71daf51e257b9a091c277c967561c Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 28 May 2019 19:18:34 +0200 Subject: [PATCH 069/250] Merge CR changes --- AmpGen/Spline.h | 1 - AmpGen/Tensor.h | 3 +-- AmpGen/Utilities.h | 8 ++++++-- src/Wigner.cpp | 6 +++--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/AmpGen/Spline.h b/AmpGen/Spline.h index 30f44280ddd..49c373654d8 100644 --- a/AmpGen/Spline.h +++ b/AmpGen/Spline.h @@ -12,7 +12,6 @@ #include "AmpGen/Expression.h" #include "AmpGen/CacheTransfer.h" #include "AmpGen/Types.h" -#include "TMatrixDUtilsfwd.h" #include "TMatrixTBase.h" #include "TMatrixD.h" diff --git a/AmpGen/Tensor.h b/AmpGen/Tensor.h index b7f4e2dffba..4fb2e95c720 100644 --- a/AmpGen/Tensor.h +++ b/AmpGen/Tensor.h @@ -121,7 +121,6 @@ namespace AmpGen void print(const bool& eval = false) const; const std::vector& uniqueElements() const { return m_uniqueElements; } - void operator+=( const Tensor& rhs ); void operator-=( const Tensor& rhs ); Tensor conjugate() const; @@ -133,7 +132,7 @@ namespace AmpGen static std::vector dim( const ARGS&... args ){ std::vector rt; auto up = std::tuple(args...); - for_each(up, [&rt]( auto& f ) { rt.emplace_back(f); } ); + for_each(up, [&rt]( const size_t& f ) { rt.emplace_back(f); } ); return rt; } private: diff --git a/AmpGen/Utilities.h b/AmpGen/Utilities.h index d2b82ad5b8e..a6e33c60256 100644 --- a/AmpGen/Utilities.h +++ b/AmpGen/Utilities.h @@ -12,7 +12,9 @@ #include #include #include -//#include +#ifdef __USE_OPENMP__ +#include +#endif #include "AmpGen/MsgService.h" #include "AmpGen/MetaUtils.h" @@ -46,7 +48,7 @@ namespace AmpGen { } template - std::string vectorToString( const std::vector& obj, const std::string& delim="", const F& functor =[](auto& f){ return f ; } ) + std::string vectorToString( const std::vector& obj, const std::string& delim="", const F& functor =[](const T& f){ return f ; } ) { std::string returnValue; std::stringstream ss; @@ -169,7 +171,9 @@ namespace AmpGen { { auto total = init; auto size = end-begin; + #ifdef __USE_OPENMP__ #pragma omp parallel for reduction( +: total ) + #endif for( int it = 0; it < size; ++it ){ total += f(*(begin+it)); } diff --git a/src/Wigner.cpp b/src/Wigner.cpp index d68f5118845..67cfdacb856 100644 --- a/src/Wigner.cpp +++ b/src/Wigner.cpp @@ -231,19 +231,19 @@ Expression AmpGen::helicityAmplitude(const Particle& particle, if( ! particle.isHead() ) myFrame.add( my_sequence ); if( particle.isStable() ) { - if( particle.spin() == 0 ) return Mz==0; + if( particle.props()->twoSpin() == 0 ) return Mz==0; // a scalar // polarisation spinor / vector etc. in the quantisation of the lab (i.e. along the z-axis or lab particle momentum) auto labPol = particle.externalSpinTensor(particle.polState(), db); ADD_DEBUG_TENSOR(labPol, db); auto inverseMyTransform = myFrame.inverse(); - if( particle.spin() == 0.5 ) + if( particle.props()->twoSpin() == 1 ) // so a fermion { auto basisSpinor_m1 = basisSpinor( 2*Mz, particle.props()->pdgID() ); auto labSpinor_m1 = inverseMyTransform( basisSpinor_m1, Transform::Representation::Bispinor ); ADD_DEBUG_TENSOR(labSpinor_m1, db); return make_cse( Bar(labSpinor_m1)(a)*labPol(a) ); } - if( particle.spin() == 1 ) + if( particle.props()->twoSpin() == 2 ) // so a spin-one boson { auto frameVector = basisVector(Mz); auto labVector = inverseMyTransform( frameVector, Transform::Representation::Vector ); From 71aec76734925227f1ac91ceaba040390aeaeb16 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 29 May 2019 11:33:13 +0200 Subject: [PATCH 070/250] Some minor changes from the GAUSS version --- AmpGen/EventList.h | 19 +++++++++++-------- AmpGen/MetaUtils.h | 1 + AmpGen/Projection.h | 9 +++++---- AmpGen/QuarkContent.h | 5 ++--- AmpGen/kMatrix.h | 4 +--- doc/release.notes | 5 ++++- 6 files changed, 24 insertions(+), 19 deletions(-) diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 67b433039e0..82913ecf1df 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -19,7 +19,7 @@ #include #ifdef __USE_OPENMP__ -#include + #include #endif namespace AmpGen @@ -106,6 +106,7 @@ namespace AmpGen return size; } } + template unsigned int extendEvent( const std::string& name, FUNCTOR func ) { @@ -118,7 +119,9 @@ namespace AmpGen template void updateCache( const FCN& fcn, const size_t& index ) { + #ifdef __USE_OPENMP__ #pragma omp parallel for + #endif for ( unsigned int i = 0; i < size(); ++i ) { ( *this )[i].setCache(fcn(getEvent(i)), index); } @@ -165,17 +168,17 @@ namespace AmpGen INFO("Filter removes: " << currentSize - size() << " / " << currentSize << " events"); } }; - DECLARE_ARGUMENT(LineColor, int ); - DECLARE_ARGUMENT(DrawStyle, std::string ); - DECLARE_ARGUMENT(Selection, std::function ); - DECLARE_ARGUMENT(WeightFunction, std::function ); - DECLARE_ARGUMENT(Branches, std::vector ); - DECLARE_ARGUMENT(EntryList, std::vector ); + DECLARE_ARGUMENT(LineColor, int); + DECLARE_ARGUMENT(DrawStyle, std::string); + DECLARE_ARGUMENT(Selection, std::function); + DECLARE_ARGUMENT(WeightFunction, std::function); + DECLARE_ARGUMENT(Branches, std::vector); + DECLARE_ARGUMENT(EntryList, std::vector); DECLARE_ARGUMENT(GetGenPdf, bool); DECLARE_ARGUMENT(CacheSize, size_t); DECLARE_ARGUMENT(Filter, std::string); DECLARE_ARGUMENT(WeightBranch, std::string); - DECLARE_ARGUMENT(ApplySym, bool ); + DECLARE_ARGUMENT(ApplySym, bool); DECLARE_ARGUMENT(Prefix, std::string); } // namespace AmpGen diff --git a/AmpGen/MetaUtils.h b/AmpGen/MetaUtils.h index ab9e3fae67c..31985fe437e 100644 --- a/AmpGen/MetaUtils.h +++ b/AmpGen/MetaUtils.h @@ -70,6 +70,7 @@ namespace AmpGen { return std::is_constructible::value && (false == std::is_same::value); } + template std::vector typelist() { std::vector< std::string > rt; diff --git a/AmpGen/Projection.h b/AmpGen/Projection.h index 3666d1a9627..9869249a0f5 100644 --- a/AmpGen/Projection.h +++ b/AmpGen/Projection.h @@ -31,17 +31,18 @@ namespace AmpGen double m_max; double m_width; public: - Projection(); + const std::string name() const ; + double operator()( const Event& evt ) const ; template - Projection( const FCN& fcn, const std::string& name, + Projection( const FCN& fcn, const std::string& name, const std::string& xAxisTitle, const size_t& nBins, const double& min, const double& max, const std::string& units = "" ) : Projection( std::function< double( const Event& )>( fcn ), name, xAxisTitle, nBins, min, max, units ) {} Projection( const std::function& fcn, const std::string& name, const std::string& xAxisTitle, const size_t& nBins, const double& min, const double& max, const std::string& units = "" ); + Projection(); TH1D* plot(const std::string& prefix="") const; - const std::string name() const ; - double operator()( const Event& evt ) const ; + std::function binFunctor() const; void setRange( const double& min, const double& max ){ m_min = (min); m_max = (max) ; } }; diff --git a/AmpGen/QuarkContent.h b/AmpGen/QuarkContent.h index 2915d574285..17d4feb7ab7 100644 --- a/AmpGen/QuarkContent.h +++ b/AmpGen/QuarkContent.h @@ -28,9 +28,8 @@ namespace AmpGen QuarkState& operator-=( const QuarkState& rhs ); QuarkState operator+ ( const QuarkState& rhs ) const; QuarkState operator- ( const QuarkState& rhs ) const; - bool operator==( const QuarkState& rhs ) const; - bool operator!=( const QuarkState& rhs ) const; - int operator[]( const size_t& index ) const; + bool operator==( const QuarkState& rhs ) const; + int operator[]( const size_t& index ) const; }; class QuarkContent diff --git a/AmpGen/kMatrix.h b/AmpGen/kMatrix.h index a6fb78cc29d..18f07095eb0 100644 --- a/AmpGen/kMatrix.h +++ b/AmpGen/kMatrix.h @@ -51,9 +51,7 @@ namespace AmpGen std::vector paramVector( const std::string& name, const unsigned int& nParam ); - Tensor getPropagator(const Tensor& kMatrix, const std::vector& phaseSpace, DebugSymbols* db = nullptr); - - + Tensor getPropagator(const Tensor& kMatrix, const std::vector& phaseSpace, DebugSymbols* db=nullptr); } // namespace AmpGen #endif /* end of include guard: AMPGEN_KMATRIX_H */ diff --git a/doc/release.notes b/doc/release.notes index 3c967441082..9f0c70a4fbd 100644 --- a/doc/release.notes +++ b/doc/release.notes @@ -3,9 +3,12 @@ ! Responsible : Tim Evans ! Purpose : !----------------------------------------------------------------------------- -!=================== AmpGen v1r2 2019-05-17 ================== +!=================== AmpGen v1r2 2019-05-29 ================== - Improved thread support for CoherentSum - Add examples/QcGenerator for Ψ(3770) decays +! 2019-05-29 - Tim Evans + - Updated ExpressionParser with improved stability. + - Removed unused / untested lineshapes AxialKaon and ObelixRho !=================== AmpGen v1r1 2019-03-22 ================== ! 2019-03-22 - Tim Evans - Added support for fitting more general final states, i.e. with multiple fermions, photons etc. From be236bb02081198f03cd47c82e957ab72c75b85f Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 29 May 2019 11:53:15 +0200 Subject: [PATCH 071/250] Fix missing definition in QuarkContent, change default number of compiler threads to hardware concurrency --- AmpGen/QuarkContent.h | 7 ++++--- src/CoherentSum.cpp | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/AmpGen/QuarkContent.h b/AmpGen/QuarkContent.h index 17d4feb7ab7..a0ac3c32644 100644 --- a/AmpGen/QuarkContent.h +++ b/AmpGen/QuarkContent.h @@ -28,8 +28,9 @@ namespace AmpGen QuarkState& operator-=( const QuarkState& rhs ); QuarkState operator+ ( const QuarkState& rhs ) const; QuarkState operator- ( const QuarkState& rhs ) const; - bool operator==( const QuarkState& rhs ) const; - int operator[]( const size_t& index ) const; + bool operator==( const QuarkState& rhs ) const; + bool operator!=( const QuarkState& rhs ) const; + int operator[]( const size_t& index ) const; }; class QuarkContent @@ -50,7 +51,7 @@ namespace AmpGen QuarkContent operator- ( const QuarkContent& rhs ) const; bool operator==( const QuarkContent& rhs ) const; bool operator!=( const QuarkContent& rhs ) const; - QuarkState operator[]( const size_t& index) const; + QuarkState operator[]( const size_t& index) const; std::vector quarks() const; }; std::ostream& operator<<( std::ostream& st, const QuarkState& qc ); diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 493e195a861..d9cc735028e 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "AmpGen/CompiledExpression.h" #include "AmpGen/ErrorPropagator.h" @@ -44,7 +45,8 @@ CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, for( auto& amp : amplitudes ) INFO( amp.first.decayDescriptor() ); m_matrixElements.resize( amplitudes.size() ); m_normalisations.resize( m_matrixElements.size(), m_matrixElements.size() ); - ThreadPool tp(1); + size_t nThreads = NamedParameter ("nCores" , std::thread::hardware_concurrency(), "Number of threads to use" ); + ThreadPool tp(nThreads); for(size_t i = 0; i < m_matrixElements.size(); ++i){ tp.enqueue( [i,this,&mps,&litudes]{ m_matrixElements[i] = TransitionMatrix( amplitudes[i].first, amplitudes[i].second, mps, this->m_evtType.getEventFormat(), this->m_dbThis); From 2c7a6d92fa2b68fe4a8b4df58211e539a6a6821c Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 9 Jun 2019 15:35:07 +0200 Subject: [PATCH 072/250] Add progress bar, BELLE2018 GLASS model for D0->Kspipi --- AmpGen/ASTResolver.h | 43 ++++---- AmpGen/AmplitudeRules.h | 1 + AmpGen/ArgumentPack.h | 87 ++++++++------- AmpGen/BinDT.h | 8 +- AmpGen/CacheTransfer.h | 35 +++--- AmpGen/CoherentSum.h | 40 +++---- AmpGen/CompiledExpression.h | 20 ++-- AmpGen/CompiledExpressionBase.h | 25 ++--- AmpGen/EventList.h | 4 +- AmpGen/EventType.h | 102 +++++++++-------- AmpGen/FitFraction.h | 4 +- AmpGen/FitResult.h | 98 +++++++--------- AmpGen/Generator.h | 80 +++++++------- AmpGen/IncoherentSum.h | 40 +++++-- AmpGen/Minimiser.h | 5 +- AmpGen/MinuitParameter.h | 2 + AmpGen/ProfileClock.h | 27 ++++- AmpGen/ProgressBar.h | 21 ++++ AmpGen/Simplify.h | 4 +- AmpGen/Spline.h | 80 +++++++------- AmpGen/SumPDF.h | 16 +-- AmpGen/ThreadPool.h | 20 +--- AmpGen/Utilities.h | 4 +- Standalone.cmake | 1 + apps/Generator.cpp | 4 +- examples/QcGenerator.cpp | 57 ++++++---- examples/SignalOnlyFitter.cpp | 3 +- src/ASTResolver.cpp | 50 ++++----- src/BinDT.cpp | 20 +--- src/CacheTransfer.cpp | 29 +++-- src/CoherentSum.cpp | 7 +- src/CompiledExpressionBase.cpp | 17 +-- src/DalitzIntegrator.cpp | 7 +- src/FitFraction.cpp | 5 +- src/FitResult.cpp | 190 ++++++++++++++++++-------------- src/IncoherentSum.cpp | 19 ++-- src/Lineshapes/GLASS.cpp | 65 ++++++----- src/Lineshapes/LASS.cpp | 2 +- src/Lineshapes/kMatrix.cpp | 4 +- src/Minimiser.cpp | 10 +- src/MinuitParameter.cpp | 7 ++ src/ParticleProperties.cpp | 3 +- src/ProgressBar.cpp | 38 +++++++ src/Spline.cpp | 10 +- src/ThreadPool.cpp | 5 +- src/ThreeBodyCalculators.cpp | 3 - 46 files changed, 715 insertions(+), 607 deletions(-) create mode 100644 AmpGen/ProgressBar.h create mode 100644 src/ProgressBar.cpp diff --git a/AmpGen/ASTResolver.h b/AmpGen/ASTResolver.h index a12e3878466..839c3991fab 100644 --- a/AmpGen/ASTResolver.h +++ b/AmpGen/ASTResolver.h @@ -17,11 +17,14 @@ namespace AmpGen { class MinuitParameter; class MinuitParameterSet; class MinuitParameterLink; - /// \class ASTResolver - /// Traverses trees in IExpression::resolveDependencies() - /// to keep track of the dependencies of the tree - /// such as sub-trees, external parameters and the event type map. + /** @ingroup ExpressionEngine class ASTResolver + @brief (Internal) class to aide in the resolution of the dependencies of expression trees. + + Traverses trees in IExpression::resolve() to keep track of the dependencies of the tree + such as sub-trees, external parameters and the mapping between particle kinematics and the + event vector. + */ class ASTResolver { public: @@ -36,30 +39,30 @@ namespace AmpGen { { auto it = m_cacheFunctions.find(name); if( it != m_cacheFunctions.end() ) return it->second->address(); - auto cacheFunction = std::make_shared(nParameters, args... ); + auto cacheFunction = std::make_shared(m_nParameters, args... ); m_cacheFunctions[name] = cacheFunction; - nParameters += cacheFunction->size(); - return nParameters - cacheFunction->size(); + m_nParameters += cacheFunction->size(); + return m_nParameters - cacheFunction->size(); } - size_t nParams() const { return nParameters ; } - bool enableCuda() const { return enable_cuda ; } - bool enableCompileConstants() const { return enable_compileTimeConstants ;} + size_t nParams() const { return m_nParameters ; } + bool enableCuda() const { return m_enable_cuda ; } + bool enableCompileConstants() const { return m_enable_compileTimeConstants ;} std::map> cacheFunctions() const; void addResolvedParameter(const IExpression* param, const std::string& thing); void addResolvedParameter(const IExpression* param, const size_t& address, const size_t& arg=0); std::string resolvedParameter( const IExpression* param ) const; private: - std::map m_resolvedParameters; - std::map> m_cacheFunctions; - std::map evtMap; /// event specification - std::map parameterMapping; /// Mapping of parameters to compile parameters - const MinuitParameterSet* mps; /// Set of MinuitParameters - std::map tempTrees; /// temporary store of sub-trees for performing cse reduction - std::map subTrees; /// Unordered sub-trees - unsigned int nParameters; /// Number of parameters - bool enable_cuda; /// flag to generate CUDA code <> - bool enable_compileTimeConstants; /// flag to enable compile time constants <> + std::map m_resolvedParameters; /// Map of parameters that have been resolved + std::map> m_cacheFunctions; /// Container of functions for calculating function cache + std::map m_evtMap; /// Event specification + std::map m_parameterMapping; /// Mapping of parameters to compile parameters + const MinuitParameterSet* m_mps; /// Set of MinuitParameters + std::map m_tempTrees; /// temporary store of sub-trees for performing cse reduction + std::map m_subTrees; /// Unordered sub-trees + unsigned int m_nParameters; /// Number of parameters + bool m_enable_cuda; /// flag to generate CUDA code <> + bool m_enable_compileTimeConstants; /// flag to enable compile time constants <> }; diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index 61f8de8bf10..235a56d3e58 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -51,6 +51,7 @@ namespace AmpGen std::vector> getMatchingRules( const EventType& type, const std::string& prefix="" ); std::vector processesThatProduce(const Particle& particle) const; + private: std::map> m_rules; }; diff --git a/AmpGen/ArgumentPack.h b/AmpGen/ArgumentPack.h index 54c1681d917..baeecf25e41 100644 --- a/AmpGen/ArgumentPack.h +++ b/AmpGen/ArgumentPack.h @@ -7,38 +7,49 @@ #include #include - namespace AmpGen { + #define DECLARE_ARGUMENT(X, Y) \ + struct X : public AmpGen::Argument { \ + template \ + X(Z val) : AmpGen::Argument(val){} \ + X() : AmpGen::Argument(){} \ + } + /** @class IArgument + @brief Virtual base class for arguments + Named arguments to functions (python-style) are given a virtual base class such + that they can be stored into an argument pack. Relies on runtime polymorphism + and should be kept away from any code that has to be fast. + */ struct IArgument { - virtual ~IArgument() = default; - + virtual ~IArgument() = default; }; + /** @class Argument - @brief Structure to pass "named" parameters to functions. - Structure to flexibly pass blocks of "Named" parameters to functions, to - approximate the behaviour of Python's named arguments. - Typical usage is for constructors with variable arguments, such as - to read data from the disk. The interface for the user is typically - \code{cpp} - EventList events("files.root", - type, - GetGenPDF(true), - WeightBranch("eventWeight"), - Branches({"K_PX","K_PY",...})); - \endcode - Internally these arguments are used to construct an ArgumentPack, and then read out - using getArg, so for this example: - \code{cpp} - auto pdfSize = args.getArg().val; - auto filter = args.getArg().val; - auto getGenPdf = args.getArg(true).val; - auto weightBranch = args.getArg().val; - auto branches = args.getArg().val; - auto applySym = args.getArg().val; - auto entryList = args.getArg().val; - \endcode - @tparam TYPE Type of the argument, such as a string, a number, a bool etc. + @brief Structure to pass "named" parameters to functions. + Structure to flexibly pass blocks of "Named" parameters to functions, to + approximate the behaviour of Python's named arguments. + Typical usage is for constructors with variable arguments, such as + to read data from the disk. The interface for the user is typically + \code{cpp} + EventList events("files.root", + type, + GetGenPDF(true), + WeightBranch("eventWeight"), + Branches({"K_PX","K_PY",...})); + \endcode + Internally these arguments are used to construct an ArgumentPack, and then read out + using getArg, so for this example: + \code{cpp} + auto pdfSize = args.getArg().val; + auto filter = args.getArg().val; + auto getGenPdf = args.getArg(true).val; + auto weightBranch = args.getArg().val; + auto branches = args.getArg().val; + auto applySym = args.getArg().val; + auto entryList = args.getArg().val; + \endcode + @tparam TYPE Type of the argument, such as a string, a number, a bool etc. */ template struct Argument : public IArgument @@ -49,15 +60,13 @@ namespace AmpGen operator TYPE() const { return val; } TYPE val = { TYPE() }; }; - - struct File : public IArgument - { - std::string name; - std::ios_base::openmode mode; - File( const std::string& name = "", const std::ios_base::openmode& mode = std::ios_base::in ) - : name( name ), mode( mode ){}; - }; + /** @class ArgumentPack + @brief Container for a set of arguments + Contains a set of arguments packed from a variadic constructor, that can + then be unpacked in the call site of the function where the named arguments + are required, as per the description in Argument. + */ class ArgumentPack { public: @@ -70,7 +79,7 @@ namespace AmpGen template ARG getArg( const DEFAULT_TYPE& default_argument = DEFAULT_TYPE() ) const { - for ( auto& param : m_parameters ) { + for ( auto param : m_parameters ) { auto ptr = dynamic_cast( param.get() ); if ( ptr != nullptr ) return *ptr; } @@ -79,12 +88,6 @@ namespace AmpGen private: std::vector> m_parameters; }; -#define DECLARE_ARGUMENT(X, Y) \ - struct X : public AmpGen::Argument { \ - template \ - X(Z val) : AmpGen::Argument(val){} \ - X() : AmpGen::Argument(){} \ - } } // namespace AmpGen #endif diff --git a/AmpGen/BinDT.h b/AmpGen/BinDT.h index c4140e242a0..2c35c0aca6a 100644 --- a/AmpGen/BinDT.h +++ b/AmpGen/BinDT.h @@ -27,17 +27,11 @@ namespace AmpGen DECLARE_ARGUMENT(MinEvents, size_t ); DECLARE_ARGUMENT(Dim, size_t ); DECLARE_ARGUMENT(Functor, std::function( const Event& )>); + DECLARE_ARGUMENT(File, std::string); class BinDT { public: - struct AddressCompressor - { - AddressCompressor() = default; - uint32_t operator[]( const void* ptr ); - uint32_t counter = {0}; - std::map elements; - }; class EndNode; class INode diff --git a/AmpGen/CacheTransfer.h b/AmpGen/CacheTransfer.h index 5be2ef201fa..6a4e162adc8 100644 --- a/AmpGen/CacheTransfer.h +++ b/AmpGen/CacheTransfer.h @@ -11,33 +11,36 @@ namespace AmpGen class CacheTransfer { - protected: - unsigned int m_address; - double m_value; - size_t m_size; public: CacheTransfer(); - CacheTransfer( const unsigned int& address, const double& value, const size_t& size=1); + CacheTransfer( const size_t& address, const double& value=0, const size_t& size=1); virtual ~CacheTransfer() = default; + + size_t address() const { return m_address ; } + virtual void transfer( CompiledExpressionBase* destination ); - virtual void print() const; - virtual unsigned int address() const { return m_address ; } - virtual unsigned int size() const { return m_size ; } + virtual void print() const; + virtual size_t size() const { return m_size ; } + + protected: + size_t m_address = {0}; + size_t m_size = {0}; + double m_value = {0}; }; class ParameterTransfer : public CacheTransfer { - protected: - unsigned int m_address; - AmpGen::MinuitParameter* m_source; - public: - ParameterTransfer( const unsigned int& address, AmpGen::MinuitParameter* source ); + ParameterTransfer( const size_t& address, AmpGen::MinuitParameter* source ); virtual ~ParameterTransfer() = default; + + size_t size() const override { return 1 ; } + void transfer( CompiledExpressionBase* destination ) override; - void print() const override; - unsigned int address() const override { return m_address ; } - unsigned int size() const override { return 1 ; } + void print() const override; + + protected: + AmpGen::MinuitParameter* m_source = {nullptr}; }; } // namespace AmpGen diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index 015dcf6779f..4f4ee8f0ce8 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -26,6 +26,10 @@ namespace AmpGen class FitFraction; class Particle; + /** @class CoherentSum + @brief An coherent sum of amplitudes + Fuck you doxygen. + */ class CoherentSum { public: @@ -47,7 +51,6 @@ namespace AmpGen real_t norm( const Bilinears& norms ) const; real_t norm() const; real_t getNorm( const Bilinears& normalisations ); - real_t get_norm() const { return m_norm ; } complex_t norm( const unsigned int& x, const unsigned int& y ) const; complex_t getVal( const Event& evt ) const; @@ -67,7 +70,6 @@ namespace AmpGen void setMC( EventList& sim ); void debug( const Event& evt, const std::string& nameMustContain=""); void generateSourceCode( const std::string& fname, const double& normalisation = 1, bool add_mt = false ); - void resync(); std::vector cacheAddresses( const EventList& evts ) const; std::vector fitFractions( const LinearErrorPropagator& linProp ); @@ -78,23 +80,23 @@ namespace AmpGen protected: std::vector> m_matrixElements; ///< Vector of (expanded) matrix elements - Bilinears m_normalisations; ///< Normalisation integrals - AmplitudeRules m_protoAmplitudes; ///< Proto amplitudes from user rule-set - Integrator<10> m_integrator; ///< Integral dispatch tool (with default unroll = 10) - TransitionMatrix m_total; ///< Total Matrix Element - EventList* m_events = {nullptr}; ///< Data events to evaluate PDF on - EventType m_evtType; ///< Final state for this amplitude - MinuitParameter* m_weightParam = {nullptr}; ///< Weight parameter (i.e. the normalised yield) - size_t m_prepareCalls = {0}; ///< Number of times prepare has been called - size_t m_lastPrint = {0}; ///< Last time verbose PDF info was printed - size_t m_printFreq = {0}; ///< Frequency to print verbose PDF info - double m_weight = {1}; ///< Weight number (i.e. the normalised yield) - double m_norm = {0}; ///< Normalisation integral - bool m_isConstant = {false}; ///< Flag for a constant PDF - bool m_dbThis = {false}; ///< Flag to generate amplitude level debugging - bool m_verbosity = {false}; ///< Flag for verbose printing - std::string m_objCache = {""}; ///< Directory that contains (cached) amplitude objects - std::string m_prefix = {""}; ///< Prefix for matrix elements + Bilinears m_normalisations; ///< Normalisation integrals + AmplitudeRules m_protoAmplitudes; ///< Proto amplitudes from user rule-set + Integrator<10> m_integrator; ///< Integral dispatch tool (with default unroll = 10) + TransitionMatrix m_total; ///< Total Matrix Element + EventList* m_events = {nullptr}; ///< Data events to evaluate PDF on + EventType m_evtType; ///< Final state for this amplitude + MinuitParameter* m_weightParam = {nullptr}; ///< Weight parameter (i.e. the normalised yield) + size_t m_prepareCalls = {0}; ///< Number of times prepare has been called + size_t m_lastPrint = {0}; ///< Last time verbose PDF info was printed + size_t m_printFreq = {0}; ///< Frequency to print verbose PDF info + double m_weight = {1}; ///< Weight number (i.e. the normalised yield) + double m_norm = {0}; ///< Normalisation integral + bool m_isConstant = {false}; ///< Flag for a constant PDF + bool m_dbThis = {false}; ///< Flag to generate amplitude level debugging + bool m_verbosity = {false}; ///< Flag for verbose printing + std::string m_objCache = {""}; ///< Directory that contains (cached) amplitude objects + std::string m_prefix = {""}; ///< Prefix for matrix elements void addMatrixElement( std::pair& particleWithCoupling, const MinuitParameterSet& mps ); }; } // namespace AmpGen diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index 16561600289..1deff2173d1 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -27,11 +27,10 @@ namespace AmpGen { private: - DynamicFCN m_fcn; - DynamicFCN>>( ARGS... )> m_fdb; - std::vector m_externals; - bool m_hasExternalsChanged; + DynamicFCN m_fcn; + DynamicFCN>(ARGS...)> m_fdb; + std::vector m_externals = {}; + bool m_hasExternalsChanged = {false}; public: @@ -41,8 +40,7 @@ namespace AmpGen std::map(), const DebugSymbols& db = {}, const MinuitParameterSet* mps = nullptr ) - : CompiledExpressionBase( expression, name, db, evtMapping ), - m_hasExternalsChanged( false ) + : CompiledExpressionBase( expression, name, db, evtMapping ) { resolve(mps); } @@ -137,7 +135,7 @@ namespace AmpGen // stream << "#pragma clang diagnostic pop\n\n" << std::endl; } - bool isReady() const override { return (m_readyFlag != nullptr && m_readyFlag->get() ) && m_fcn.isLinked(); } + bool isReady() const override { return m_fcn.isLinked(); } bool isLinked() const { return m_fcn.isLinked() ; } size_t returnTypeSize() const override { return sizeof( RETURN_TYPE ); } @@ -207,7 +205,7 @@ namespace AmpGen make_expression( const Expression& expression, const std::string& name , const bool& verbose=false) { CompiledExpression rt(expression,name); - rt.compile("", true); + rt.compile(); rt.prepare(); return rt; } @@ -218,7 +216,7 @@ namespace AmpGen const MinuitParameterSet& mps ) { CompiledExpression rt(expression,name,{},{},&mps); - rt.compile("", true); + rt.compile(); rt.prepare(); return rt; } @@ -230,7 +228,7 @@ namespace AmpGen const MinuitParameterSet& mps ) { CompiledExpression rt(expression,name,evtMap,{},&mps); - rt.compile("", true); + rt.compile(); rt.prepare(); return rt; } diff --git a/AmpGen/CompiledExpressionBase.h b/AmpGen/CompiledExpressionBase.h index 5051ae3b5bd..d857f1d45cc 100644 --- a/AmpGen/CompiledExpressionBase.h +++ b/AmpGen/CompiledExpressionBase.h @@ -31,17 +31,6 @@ namespace AmpGen */ class CompiledExpressionBase { - protected: - Expression m_obj; - std::string m_name; - std::string m_progName; - DebugSymbols m_db; - std::map m_evtMap; - std::shared_future* m_readyFlag = {nullptr}; - std::vector> m_dependentSubexpressions; - std::vector> m_debugSubexpressions; - std::vector> m_cacheTransfers; - ASTResolver* m_resolver = {nullptr}; public: CompiledExpressionBase( const Expression& expression, const std::string& name, @@ -52,7 +41,7 @@ namespace AmpGen void resolve(const MinuitParameterSet* mps = nullptr); void prepare(); - void compile(const std::string& fname="", const bool& wait = false ); + void compile(const std::string& fname=""); void to_stream( std::ostream& stream ) const; unsigned int hash() const; std::string name() const; @@ -66,8 +55,18 @@ namespace AmpGen virtual std::string fcnSignature() const = 0; virtual std::string args() const = 0; virtual void print() const = 0; - virtual ~CompiledExpressionBase() = default; + virtual ~CompiledExpressionBase() = default; virtual size_t returnTypeSize() const = 0; + protected: + Expression m_obj; + std::string m_name; + std::string m_progName; + DebugSymbols m_db; + std::map m_evtMap; + std::vector> m_dependentSubexpressions; + std::vector> m_debugSubexpressions; + std::vector> m_cacheTransfers; + ASTResolver* m_resolver = {nullptr}; private: void addDebug( std::ostream& stream ) const; diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 82913ecf1df..5534f71aef2 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -18,7 +18,7 @@ #include #include -#ifdef __USE_OPENMP__ +#ifdef _OPENMP #include #endif @@ -119,7 +119,7 @@ namespace AmpGen template void updateCache( const FCN& fcn, const size_t& index ) { - #ifdef __USE_OPENMP__ + #ifdef _OPENMP #pragma omp parallel for #endif for ( unsigned int i = 0; i < size(); ++i ) { diff --git a/AmpGen/EventType.h b/AmpGen/EventType.h index ca00861dbb4..25f4edd11e5 100644 --- a/AmpGen/EventType.h +++ b/AmpGen/EventType.h @@ -12,54 +12,68 @@ namespace AmpGen class Projection; class Event; /**@class EventType - * Deals with final state configuration of events, - * specifically dealing with the ordering of particles in trees. + Deals with final state configuration of events, + specifically dealing with the ordering of particles in trees. */ class EventType { - private: - std::string m_mother; ///< name of decaying particle - double m_motherMass; ///< mass of decaying particle - std::vector m_particleNames; ///< names of decay products - std::vector m_particleNamesPickled; ///< names of decay product pickled for ROOT - std::vector m_particleMasses; ///< masses of decay products - bool m_timeDependent; - std::vector m_eventTypeExtensions; ///< extended event data - std::pair m_dim; ///< Rank of the relevant transition matrix - public: - EventType() = default; - EventType( const std::vector&, const bool& isTD = false ); - std::map getEventFormat( const bool& outputNames = false ) const; - - std::pair count(const size_t& index) const; ///< Count the number of particles with name. - std::pair minmax( const std::vector& indices, bool isGeV = false ) const; - std::vector> getBosePairs() const; - std::vector masses() const; - std::string mother() const; - double mass( const size_t& index ) const; - double motherMass() const; - std::vector finalStates() const; - bool isTimeDependent() const; - size_t eventSize() const; - size_t size() const; - size_t dof() const; - std::string operator[]( const size_t& index ) const; - std::string decayDescriptor() const; - std::string label( const size_t& index, bool isRoot = true ) const; - std::string label( const std::vector& index, bool isRoot = true ) const; - std::vector defaultProjections(const size_t& nBins) const; - Projection projection(const size_t& nBins, const std::vector& indices, const std::string& observable = "mass2") const; - - bool operator==( const EventType& other ) const; - bool has( const std::string& name ) const; - EventType conj( const bool& headOnly = 0, const bool& dontConjHead = 0 ) const; - - void setMotherMass( const double& mass ){ m_motherMass = mass ; } - void extendEventType( const std::string& branch ); - std::function symmetriser() const; - ///< calculates the number of spin indices associated with the initial and final state, i.e. the rank of the relevant transition matrix. - std::pair dim() const; + public: + /// @constructor Default constructor + EventType() = default; + + /// @constructor Takes a list of particles, beginning with the head of the decay and + /// then then final state particles, and a flag as to whether to include time dependence. + EventType( const std::vector&, const bool& isTD = false ); + + /// @function Returns the CP-conjugated event type. Can also require that only the initial/ + /// final state is conjugated. By default, conjugates both. + EventType conj( const bool& headOnly = 0, const bool& dontConjHead = 0 ) const; + + /// @function Returns the event format, that matches between expressions and the names used in Particle. + std::map getEventFormat( const bool& outputNames = false ) const; + + /// @function Counts the number of particles in this event type with + /// the same name as the index'th name. + std::pair count(const size_t& index) const; + std::pair minmax( const std::vector& indices, bool isGeV = false ) const; + std::vector> getBosePairs() const; + std::vector masses() const; + std::string mother() const; + double mass( const size_t& index ) const; + double motherMass() const; + std::vector finalStates() const; + bool isTimeDependent() const; + size_t eventSize() const; + size_t size() const; + size_t dof() const; + std::string operator[]( const size_t& index ) const; + std::string decayDescriptor() const; + std::string label( const size_t& index, bool isRoot = true ) const; + std::string label( const std::vector& index, bool isRoot = true ) const; + std::vector defaultProjections(const size_t& nBins) const; + Projection projection(const size_t& nBins, const std::vector& indices, const std::string& observable = "mass2") const; + + bool operator==( const EventType& other ) const; + bool has( const std::string& name ) const; + + void extendEventType( const std::string& branch ); + + /// @function Functor to randomly symmetrise data of this event type, using the Fisher-Yates shuffle. + std::function symmetriser() const; + + /// @function Calculates the number of spin indices associated with the initial and final state, i.e. the rank of the relevant transition matrix. + std::pair dim() const; + + private: + std::string m_mother; ///< name of decaying particle + double m_motherMass; ///< mass of decaying particle + std::vector m_particleNames; ///< names of decay products + std::vector m_particleNamesPickled; ///< names of decay product pickled for ROOT + std::vector m_particleMasses; ///< masses of decay products + bool m_timeDependent; ///< Flag to include a decay time as the last element in the event vector + std::vector m_eventTypeExtensions; ///< extended event data + std::pair m_dim; ///< Rank of the relevant transition matrix }; std::ostream& operator<<( std::ostream& os, const EventType& type ); } // namespace AmpGen diff --git a/AmpGen/FitFraction.h b/AmpGen/FitFraction.h index 29142f17bdc..99012395c40 100644 --- a/AmpGen/FitFraction.h +++ b/AmpGen/FitFraction.h @@ -13,11 +13,10 @@ namespace AmpGen class EventType; class Particle; - class FitFraction { public: - FitFraction(const std::string& line, const AmpGen::EventType& evtType); + FitFraction(const std::string& line); FitFraction(const std::string& name, const double& frac, const double& err); FitFraction() = default; @@ -32,6 +31,7 @@ namespace AmpGen double m_value; double m_error; }; + bool operator <(const FitFraction& lhs, const FitFraction& rhs); bool operator >(const FitFraction& lhs, const FitFraction& rhs); bool operator ==(const FitFraction& lhs, const FitFraction& rhs); diff --git a/AmpGen/FitResult.h b/AmpGen/FitResult.h index e16103e7798..ed39584dbc6 100644 --- a/AmpGen/FitResult.h +++ b/AmpGen/FitResult.h @@ -3,7 +3,6 @@ #include "TMatrixD.h" -#include "AmpGen/EventType.h" #include "AmpGen/FitFraction.h" #include "AmpGen/MinuitParameter.h" #include "AmpGen/Utilities.h" @@ -15,76 +14,63 @@ namespace AmpGen class FitResult { + public: + FitResult(); + FitResult( const FitResult& other ); + FitResult( const std::string& filename ); + FitResult( const Minimiser& mini ); + FitResult( const MinuitParameterSet& mps, const TMatrixD& covMini ); + + void addObservable( const std::string& name, const double& F ); + void addChi2( const double& chi2, const double& nBins ); + void addFractions( const std::vector& fractions ); + void addFraction( const std::string& name, const double& frac, const double& err ); + void setCov( const size_t& x, const size_t& y, const double& F ); + void writeToFile( const std::string& fname ); + void clearFitFractions(); + + bool readFile( const std::string& fname ); + + double chi2() const; + double LL() const; + double dof() const; + double cov(const size_t& x, const size_t& y ) const; + double cov(const std::string& x, const std::string& y ) const; + double correlation( const std::string& x, const std::string& y ) const; + + int status() const; + int nParam() const; + int nBins() const; + + std::map observables() const; + std::shared_ptr mps() const; + + std::vector fitFractions() const; + std::vector parameters() const; + std::vector floating(const bool& extended = false) const; + TMatrixD cov() const; + + void print() const; + + TMatrixD getReducedCovariance( const bool& extended = false ) const; + LinearErrorPropagator getErrorPropagator( const bool& extended = false ) const; + private: + std::shared_ptr m_mps; double m_chi2 = {0}; double m_LL = {-999}; double m_nBins = {0}; double m_nParam = {0}; int m_status = {-1}; bool m_fitted = {false}; - EventType m_eventType; std::map m_observables; std::vector m_fitFractions; TMatrixD m_covarianceMatrix; - std::shared_ptr m_mps; std::map m_covMapping; - std::string getLastLine( std::ifstream& in ) const; void addToParameters( const std::string& line ); void addToObservables( const std::string& line ); void setFitQuality( const std::string& line ); - - public: - FitResult( const FitResult& other ); - - void addObservable( const std::string& name, const double& F ); - FitResult( const Minimiser& mini ); - FitResult( const MinuitParameterSet& mps, const TMatrixD& covMini ); - - FitResult( const std::string& filename, const EventType& evtType = EventType() ); - FitResult() = default; - - bool readFile( const std::string& fname ); - void writeToFile( const std::string& fname ); - - double chi2() const { return m_chi2; } - double LL() const { return m_LL; } - int status() const { return m_status; } - int nParam() const { return m_nParam; } - int nBins() const { return m_nBins; } - - EventType eventType() const { return m_eventType; } - std::map observables() const { return m_observables; } - std::vector fitFractions() const { return m_fitFractions; } - std::shared_ptr mps() const { return m_mps; } - - double dof() const { return m_nBins - m_nParam - 1; } - std::vector getParameters() const; - std::vector getFitFractions() const { return m_fitFractions; } - MinuitParameterSet* MPS() const { return &( *m_mps ); } - TMatrixD cov() const { return m_covarianceMatrix; } - double cov( const size_t& x, const size_t& y ) const { return m_covarianceMatrix( x, y ); } - double cov( const std::string& x, const std::string& y ) const { return m_covarianceMatrix( m_covMapping.at(x), m_covMapping.at(y) ); } - - void print() const; - - std::vector getFloating( const bool& extended = false ) const; - TMatrixD getReducedCovariance( const bool& extended = false ) const; - LinearErrorPropagator getErrorPropagator( const bool& extended = false ) const; - void addChi2( const double& chi2, const double& nBins ); - void addFractions( const std::vector& fractions ); - void addFraction( const std::string& name, const double& frac, const double& err ) - { - m_fitFractions.emplace_back( name, frac, err ); - } - void clearFitFractions() { m_fitFractions.clear(); } - void setCov( const size_t& x, const size_t& y, const double& F ) { m_covarianceMatrix( x, y ) = F; } - double correlation( const std::string& x, const std::string& y ) - { - auto ix = m_covMapping[x]; - auto iy = m_covMapping[y]; - return m_covarianceMatrix( ix, iy ) / sqrt( m_covarianceMatrix( ix, ix ) * m_covarianceMatrix( iy, iy ) ); - } }; } // namespace AmpGen diff --git a/AmpGen/Generator.h b/AmpGen/Generator.h index 42779b8594e..b338c41bf92 100644 --- a/AmpGen/Generator.h +++ b/AmpGen/Generator.h @@ -5,7 +5,8 @@ #include "AmpGen/EventType.h" #include "AmpGen/PhaseSpace.h" #include "AmpGen/Utilities.h" - +#include "AmpGen/ProfileClock.h" +#include "AmpGen/ProgressBar.h" namespace AmpGen { template @@ -39,31 +40,20 @@ namespace AmpGen void setBlockSize( const size_t& blockSize ) { m_generatorBlock = blockSize; } void setNormFlag( const bool& normSetting ) { m_normalise = normSetting; } - template - void fillEventListPhaseSpace( EventList& list, const size_t& N, const size_t& cacheSize, HARD_CUT cut ) + template void fillEventListPhaseSpace( EventList& list, const size_t& N, const size_t& cacheSize, HARD_CUT cut ) { - unsigned int rejected = 0; - #ifdef DEBUGLEVEL - auto t_start = std::chrono::high_resolution_clock::now(); - #endif list.reserve( N ); while( list.size() < N ){ Event newEvent = m_gps.makeEvent( cacheSize ); newEvent.setWeight( 1 ); if ( cut( newEvent ) ) list.push_back( newEvent ); - else rejected ++; } - #ifdef DEBUGLEVEL - auto t_end = std::chrono::high_resolution_clock::now(); - double time = std::chrono::duration( t_end - t_start ).count(); - #endif - DEBUG( "Stage 1 efficiency = " << 100. * list.size() / ( list.size() + rejected ) << "%, yield = " << list.size() - << " time = " << time ); } + template void fillEventList( PDF& pdf, EventList& list, const size_t& N ) { - fillEventList( pdf, list, N, []( const Event& evt ) { return 1; } ); + fillEventList( pdf, list, N, []( const Event& /*evt*/ ) { return 1; } ); } template @@ -74,17 +64,20 @@ namespace AmpGen return; } double normalisationConstant = m_normalise ? 0 : 1; - size_t size0 = list.size(); + auto size0 = list.size(); auto tStartTotal = std::chrono::high_resolution_clock::now(); pdf.reset( true ); + ProgressBar pb(60, trimmedString(__PRETTY_FUNCTION__) ); + ProfileClock t_phsp, t_eval, t_acceptReject; while ( list.size() - size0 < N ) { - auto t_start = std::chrono::high_resolution_clock::now(); EventList mc( m_eventType ); + t_phsp.start(); fillEventListPhaseSpace( mc, m_generatorBlock, pdf.size(), cut ); - + t_phsp.stop(); + t_eval.start(); pdf.setEvents( mc ); pdf.prepare(); - + t_eval.stop(); if ( normalisationConstant == 0 ) { double max = 0; for ( auto& evt : mc ) { @@ -94,32 +87,36 @@ namespace AmpGen normalisationConstant = max * 1.5; INFO( "Setting normalisation constant = " << normalisationConstant ); } + auto previousSize = list.size(); + t_acceptReject.start(); + #ifdef _OPENMP + #pragma omp parallel for + #endif + for ( size_t i=0;i< mc.size(); ++i ) mc[i].setGenPdf(pdf.prob_unnormalised(mc[i])); - unsigned int previousSize = list.size(); - for ( auto& evt : mc ) { - double value = pdf.prob_unnormalised( evt ); - if ( value > normalisationConstant ) { - WARNING( "PDF value exceeds norm value: " << value << " " << normalisationConstant ); - } - if ( value > normalisationConstant * m_rnd->Rndm() ) { - evt.setGenPdf( value ); - list.push_back( evt ); + for( auto& evt : mc ){ + if ( evt.genPdf() > normalisationConstant ) { + std::cout << std::endl; + WARNING( "PDF value exceeds norm value: " << evt.genPdf() << " > " << normalisationConstant ); } + if ( evt.genPdf() > normalisationConstant * m_rnd->Rndm() ) list.push_back( evt ); if ( list.size() - size0 == N ) break; } - auto t_end = std::chrono::high_resolution_clock::now(); - // double time = std::chrono::duration(t_end-t_stage2).count() ; - double timeTotal = std::chrono::duration( t_end - t_start ).count(); - INFO( "Generator Efficiency = " << 100. * ( list.size() - previousSize ) / (double)m_generatorBlock - << "% integrated yield = " << list.size() << ", time = " << timeTotal << "ms" ); + t_acceptReject.stop(); + double time = std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); + double efficiency = 100. * ( list.size() - previousSize ) / (double)m_generatorBlock; + pb.print( double(list.size()) / double(N), " ε[gen] = " + mysprintf("%.2f",efficiency) + "% , " + std::to_string(int(time/1000.)) + " seconds" ); if ( list.size() == previousSize ) { ERROR( "No events generated, PDF: " << typeof() << " is likely to be malformed" ); break; } - } - double time = - std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); - INFO( "Generated " << N << " events in " << time << " ms" ); + } + pb.finish(); + double time = std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); + INFO( "Generated " << N << " events in " << time << " ms" ); + INFO( "Generating phase space : " << t_phsp << " ms"); + INFO( "Evaluating PDF : " << t_eval << " ms"); + INFO( "Doing accept/reject : " << t_acceptReject << " ms"); } template ::value>::type> @@ -129,8 +126,6 @@ namespace AmpGen fillEventList( pdf, evts, nEvents ); return evts; } - // template ::value>::type> EventList generate(const size_t& nEvents, const size_t& cacheSize=0) { EventList evts( m_eventType ); @@ -143,12 +138,15 @@ namespace AmpGen FCN m_fcn; public: void prepare(){}; - void setEvents( AmpGen::EventList& evts ){}; + void setEvents( AmpGen::EventList& /*evts*/ ){}; double prob_unnormalised( const AmpGen::Event& evt ) const { return m_fcn(evt); } PDFWrapper( const FCN& fcn ) : m_fcn(fcn) {} size_t size() const { return 0; } - void reset( const bool& flag = false ){}; + void reset( const bool& /*flag*/ = false ){}; }; + + template PDFWrapper make_pdf(const FCN& fcn){ return PDFWrapper(fcn) ; } + extern "C" void PyGenerate( const char* eventType, double* out, const unsigned int size ); } // namespace AmpGen #endif diff --git a/AmpGen/IncoherentSum.h b/AmpGen/IncoherentSum.h index c4c32bb6b16..e60c34bb443 100644 --- a/AmpGen/IncoherentSum.h +++ b/AmpGen/IncoherentSum.h @@ -1,5 +1,5 @@ -#ifndef AMPGEN_FASTINCOHERENTSUM_H -#define AMPGEN_FASTINCOHERENTSUM_H +#ifndef AMPGEN_INCOHERENTSUM_H +#define AMPGEN_INCOHERENTSUM_H #include #include @@ -19,22 +19,46 @@ namespace AmpGen class FitFraction; class LinearErrorPropagator; class MinuitParameterSet; - + + /** @class IncoherentSum + @brief An incoherent sum of resonances, traditionally considered as an approximate background model. + An incoherent sum of resonant contributions, where at a positiion in phase-space @f$\psi@f$, + the (unnormalised) probability density is given by + @f[ + \mathcal{P}(\psi) = \sum_{i} \left| g_i \mathcal{A}_i(\psi) \right|^2, + @f] + where @f$\mathcal{P}(\psi)@f$ is the probability, @f$g_i@f$ is the coupling to an isobar channel, + and @f$\mathcal{A}_i(\psi)@f$ is the amplitude of the ith channel. + what's going on ??? + */ class IncoherentSum : public CoherentSum { public: - IncoherentSum( const EventType& finalStates, const AmpGen::MinuitParameterSet& mps, const std::string& prefix = "Inco" ); - - double getVal( const Event& evt ) const; - double operator()( const Event& evt ) const; + /** @constructor Constructs an incoherentSum from the type of event this is expected to describe, + and a set of parameters that are expected to be able to describe it. + @param eventType The type of event that this PDF should describe + @param mps The parameter set of couplings, masses, etc. + @param prefix Prefix required for the ``head'' decays for this event type. */ + IncoherentSum(const EventType& eventType, const AmpGen::MinuitParameterSet& mps, const std::string& prefix = "Inco"); + + /// @function Evaluates the normalised probability for an event. double prob( const Event& evt ) const; + + /// @function Calculates the unnormalised probability for an event. double prob_unnormalised( const Event& evt ) const; - void prepare(); + + /** @function Returns the normalisation for this PDF, given by + @f[ + \mathcal{N} = \int d\psi \varepsilon(\psi) \mathcal{P}(\psi) \approx \sum_i \frac{\mathcal{P}(\psi_i)}{\mathcal{P}^\prime(\psi_i)} + @f] + where the sum is over a simulated sample, generated with PDF @f$\mathcal{P}^\prime(\psi)@f$. */ double norm() const; complex_t norm(const size_t& i, const size_t& j){ return i==j ? m_normalisations.get(i, 0) : 0; } complex_t norm(const size_t& i) { return m_normalisations.get(i, 0); } double norm( const Bilinears& norms ) const; std::vector fitFractions( const LinearErrorPropagator& linProp ); + + void prepare(); }; } // namespace AmpGen diff --git a/AmpGen/Minimiser.h b/AmpGen/Minimiser.h index 815235b1e28..02772ab3a8b 100644 --- a/AmpGen/Minimiser.h +++ b/AmpGen/Minimiser.h @@ -29,7 +29,7 @@ namespace AmpGen class Minimiser { public: - template + template Minimiser(TYPE& fitFunction, MinuitParameterSet* mps) : m_parSet(mps) { @@ -72,7 +72,8 @@ namespace AmpGen unsigned int m_nParams = {0}; unsigned int m_lastPrint = {0}; unsigned int m_printLevel = {0}; - + double m_ll_zero = {0}; + bool m_normalise = {false}; }; } // namespace AmpGen #endif diff --git a/AmpGen/MinuitParameter.h b/AmpGen/MinuitParameter.h index 0aa2c51d678..6544084631f 100644 --- a/AmpGen/MinuitParameter.h +++ b/AmpGen/MinuitParameter.h @@ -18,6 +18,8 @@ namespace AmpGen MinuitParameter() = default; MinuitParameter(const std::string& name, const Flag& iFixInit, const double& mean, const double& step, const double& min = 0, const double& max = 0 ); + MinuitParameter(const std::string& name, const double& mean, const double& step, + const double& min = 0, const double& max = 0 ); Flag iFixInit() const; bool hidden() const; diff --git a/AmpGen/ProfileClock.h b/AmpGen/ProfileClock.h index 008b834cad1..b625b72e55e 100644 --- a/AmpGen/ProfileClock.h +++ b/AmpGen/ProfileClock.h @@ -6,11 +6,18 @@ namespace AmpGen{ struct ProfileClock { - std::chrono::time_point t_start; - std::chrono::time_point t_end; - ProfileClock() : t_start( std::chrono::high_resolution_clock::now()) {} - void stop(){ t_end = std::chrono::high_resolution_clock::now() ; } - operator double() const { return std::chrono::duration( t_end - t_start ).count() ; } ; + std::chrono::time_point t_start; + std::chrono::time_point t_end; + double t_duration = {0}; + + ProfileClock() : t_start(std::chrono::high_resolution_clock::now()) {} + void stop() + { + t_end = std::chrono::high_resolution_clock::now() ; + t_duration += std::chrono::duration( t_end - t_start ).count(); + } + void start(){ t_start = std::chrono::high_resolution_clock::now() ; } + operator double() const { return t_duration; } ; }; template @@ -21,5 +28,15 @@ namespace AmpGen{ INFO( typeof() << " " << t/double(N) << "[ms] per iteration" ); return t; } + + template + double Profile2( const FCN& fcn ){ + ProfileClock t; + auto z = 0 ; + for( size_t i = 0 ; i < N; ++i ) z += fcn(); + t.stop(); + INFO( typeof() << " " << t/double(N) << "[ms] per iteration; " << z ); + return t; + } } #endif diff --git a/AmpGen/ProgressBar.h b/AmpGen/ProgressBar.h new file mode 100644 index 00000000000..258fe5f9202 --- /dev/null +++ b/AmpGen/ProgressBar.h @@ -0,0 +1,21 @@ +#ifndef AMPGEN_PROGRESSBAR_H +#define AMPGEN_PROGRESSBAR_H + +#include +namespace AmpGen { + class ProgressBar { + public: + ProgressBar(const size_t& width, const std::string& context); + ~ProgressBar(); + void print(const double& percentage, const std::string& message=""); + void finish(); + private: + size_t m_width; + int m_lastPercent; + std::string m_context; + std::string m_lastMessage = {""}; + bool m_finished = {false}; + }; +} + +#endif diff --git a/AmpGen/Simplify.h b/AmpGen/Simplify.h index 5ecdc59be87..882d081ac9f 100644 --- a/AmpGen/Simplify.h +++ b/AmpGen/Simplify.h @@ -8,6 +8,9 @@ #include "AmpGen/Expression.h" namespace AmpGen { + + Expression Simplify(const Expression& expression ); + class NormalOrderedExpression { public: struct Term { @@ -31,7 +34,6 @@ namespace AmpGen { std::vector m_terms; bool m_expandSubTrees; }; - Expression Simplify(const Expression& expression ); } #endif diff --git a/AmpGen/Spline.h b/AmpGen/Spline.h index 49c373654d8..4ce5696911b 100644 --- a/AmpGen/Spline.h +++ b/AmpGen/Spline.h @@ -23,54 +23,50 @@ namespace AmpGen{ class SplineTransfer : public CacheTransfer { - private: - TMatrixD m_transferMatrix; - std::vector m_parameters; - unsigned int m_nKnots; - double m_min; - double m_max; - unsigned int m_address; + public: + SplineTransfer(); + SplineTransfer( const SplineTransfer& other ); + SplineTransfer( const size_t& address, const unsigned int& N, const double& min, const double& max ); + void transfer( CompiledExpressionBase* destination ) override; + bool isConfigured(); + void set( const unsigned int& N, AmpGen::MinuitParameter* f ); + void set( const unsigned int& N, const double& value ); + void print() const override; + size_t size() const override { return 2*m_nKnots; } - public: - SplineTransfer(); - SplineTransfer( const SplineTransfer& other ); - SplineTransfer( const unsigned int& address, const unsigned int& N, const double& min, const double& max ); - void transfer( CompiledExpressionBase* destination ) override; + private: + TMatrixD m_transferMatrix; + std::vector m_parameters; + size_t m_nKnots; + double m_min; + double m_max; + }; - bool isConfigured(); + class Spline : public IExpression { + public: + Spline( const std::string& name, + const size_t& nKnots, + const double& min, + const double& max ); - void set( const unsigned int& N, AmpGen::MinuitParameter* f ); - void set( const unsigned int& N, const double& value ); + Spline( const Spline& spline, const Expression& x ); + void resolve( ASTResolver& resolver ) const override ; + std::string to_string(const ASTResolver* resolver=nullptr) const override; + operator Expression() ; + complex_t operator()() const override ; + Expression operator()( const Expression& x ); + Expression eval() const ; - void setAddress( const unsigned int& address ); - void print() const override; - unsigned int address() const override { return m_address ; } - unsigned int size() const override { return 2*m_nKnots ; } - }; - - struct Spline : public IExpression { - Array m_points; - std::string m_name; - size_t m_nKnots; - double m_min; - double m_max; - Expression m_x; - Expression m_eval; - Spline( const std::string& name, - const size_t& nKnots, - const double& min, - const double& max ); - - Spline( const Spline& spline, const Expression& x ); - void resolve( ASTResolver& resolver ) const override ; - std::string to_string(const ASTResolver* resolver=nullptr) const override; - operator Expression() ; - complex_t operator()() const override ; - Expression operator()( const Expression& x ); - Expression eval() const ; + Array m_points; + std::string m_name; + size_t m_nKnots; + double m_min; + double m_max; + Expression m_x; + Expression m_eval; }; Expression getSpline( const std::string& name, const AmpGen::Expression& x, const std::string& arrayName, - AmpGen::DebugSymbols* dbexpressions = nullptr, const bool& continueSpline = false ); + AmpGen::DebugSymbols* dbexpressions = nullptr, const bool& continueSpline = false ); } #endif diff --git a/AmpGen/SumPDF.h b/AmpGen/SumPDF.h index 4a6aa4c7fa3..dc9ab4e96e3 100644 --- a/AmpGen/SumPDF.h +++ b/AmpGen/SumPDF.h @@ -8,17 +8,17 @@ #include "AmpGen/ProfileClock.h" #include -/* A SumPDF is the log-likelihood of the form - -2*LL(event) = -2*log( Sum( i, P_i(event) ) ) - Where P_i are some probability density functions - The sum is variadically unrolled at compile time, i.e. the wrapper - is the same for 1..N pdfs. The unrolling should be properly inlined, - hence N can be reasonably large with out afflicting either - compile time or binary size. - */ namespace AmpGen { + /** @class SumPDF + @brief A pdf with the log-likelihood of the form + -2*LL(event) = -2*log( Sum( i, P_i(event) ) ) + Where P_i are some probability density functions + The sum is variadically unrolled at compile time, i.e. the wrapper + is the same for 1..N pdfs. The unrolling should be properly inlined, + hence N can be reasonably large with out afflicting either + compile time or binary size. */ template class SumPDF { diff --git a/AmpGen/ThreadPool.h b/AmpGen/ThreadPool.h index 7604c971ddb..d00031f4a1c 100644 --- a/AmpGen/ThreadPool.h +++ b/AmpGen/ThreadPool.h @@ -4,7 +4,6 @@ /* @class ThreadPool ThreadPool.h AmpGen/ThreadPool.h * Thread pool implementation taken from https://github.com/progschj/ThreadPool * Modified to allow explicit clearing of queues. - * A single static thread pool exists that can be used as a sceduler. * * Copyright (c) 2012 Jakob Progsch, Václav Zeman * @@ -48,27 +47,12 @@ namespace AmpGen class ThreadPool { public: - static size_t nThreads; - + ThreadPool(const size_t& nt); ~ThreadPool(); - - template static auto schedule( F&& f, Args&&... args ) -> std::future::type> - { - return getMe()->enqueue( f, args... ); - } - template auto enqueue(F&& f, Args&&... args) -> std::future::type>; - - ThreadPool(const size_t& nt); void waitForStoppedThreads(); + private: - static ThreadPool* gThreadPool; - static ThreadPool* getMe() - { - if ( !gThreadPool ) - gThreadPool = new ThreadPool(ThreadPool::nThreads); - return gThreadPool; - } std::vector m_workers; std::queue> m_tasks; std::mutex m_queue_mutex; diff --git a/AmpGen/Utilities.h b/AmpGen/Utilities.h index a6e33c60256..afb78bdcf65 100644 --- a/AmpGen/Utilities.h +++ b/AmpGen/Utilities.h @@ -12,7 +12,7 @@ #include #include #include -#ifdef __USE_OPENMP__ +#ifdef _OPENMP #include #endif @@ -171,7 +171,7 @@ namespace AmpGen { { auto total = init; auto size = end-begin; - #ifdef __USE_OPENMP__ + #ifdef _OPENMP #pragma omp parallel for reduction( +: total ) #endif for( int it = 0; it < size; ++it ){ diff --git a/Standalone.cmake b/Standalone.cmake index 9a47e5a5cec..f78be327551 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -127,6 +127,7 @@ target_compile_options(AmpGen -Wno-unknown-pragmas -Wnon-virtual-dtor -Woverloaded-virtual + -march=native $<$:-Ofast>) if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") diff --git a/apps/Generator.cpp b/apps/Generator.cpp index 804530fe7d0..315cfb3049c 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -81,6 +81,7 @@ int main( int argc, char** argv ) #ifdef _OPENMP unsigned int concurentThreadsSupported = std::thread::hardware_concurrency(); unsigned int nCores = NamedParameter( "nCores", concurentThreadsSupported, "Number of cores to use (OpenMP only)" ); + INFO("Using: " << nCores << " / " << concurentThreadsSupported << " threads" ); omp_set_num_threads( nCores ); omp_set_dynamic( 0 ); #endif @@ -106,8 +107,7 @@ int main( int argc, char** argv ) GenerateEvents( accepted, sig, phsp , nEvents, blockSize, &rand ); } else if ( gen_type == "PolarisedSum" ){ - PolarisedSum sig( eventType, MPS ); - + PolarisedSum sig( eventType, MPS ); RecursivePhaseSpace phsp( sig.matrixElements()[0].decayTree.quasiStableTree() , eventType, &rand ); GenerateEvents( accepted, sig, phsp, nEvents, blockSize, &rand ); } diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp index 187ac775991..33ff7459c76 100644 --- a/examples/QcGenerator.cpp +++ b/examples/QcGenerator.cpp @@ -107,6 +107,7 @@ template class Psi3770 { PhaseSpace m_tagPhsp; PhaseSpace m_headPhsp; bool m_printed = {false}; + bool m_ignoreQc = {NamedParameter("IgnoreQC",false)}; size_t m_blockSize = {1000000}; public: template std::tuple @@ -147,16 +148,18 @@ template class Psi3770 { INFO( "Signal: R = " << round(std::get<0>(z1),5) << "; δ = " << round(std::get<1>(z1),3) << "° ; r = " << round(std::get<2>(z1),5) ); INFO( "Tag : R = " << round(std::get<0>(z2),5) << "; δ = " << round(std::get<1>(z2),3) << "° ; r = " << round(std::get<2>(z2),5) ); } - complex_t operator()( const DTEvent& event ) const { return operator()( event.signal, event.tag ); } - complex_t operator()( const Event& signal, const Event& tag) const { return m_signal(signal)*m_tagBar(tag) - m_signalBar(signal) * m_tag(tag); } - double P(const DTEvent& event) const { return std::norm(operator()(event)); } + complex_t operator()(const DTEvent& event ) const { return operator()( event.signal, event.tag ); } + complex_t operator()(const Event& signal, const Event& tag) const { return m_signal(signal)*m_tagBar(tag) - m_signalBar(signal) * m_tag(tag); } + double P(const DTEvent& event) const { return m_ignoreQc ? prob_noQC(event) : std::norm(operator()(event)); } double prob_noQC (const DTEvent& event) const { return std::norm(m_signal(event.signal)*m_tagBar(event.tag)) + std::norm(m_signalBar(event.signal)*m_tag(event.tag)); } DTEvent generatePhaseSpace() { return DTEvent( m_signalPhsp.makeEvent(), m_tagPhsp.makeEvent() ); } DTEventList generate( const size_t& N ) { DTEventList output( m_signalType, m_tagType ); - double norm = -1; - ProfileClock pc; + ProgressBar pb(60, trimmedString(__PRETTY_FUNCTION__)); + auto tStartTotal = std::chrono::high_resolution_clock::now(); + int currentSize = 0; + double norm = -1; while( output.size() < N ){ auto events = generatePHSP(m_blockSize); if(norm == -1 ){ @@ -164,23 +167,26 @@ template class Psi3770 { norm *= 1.5; INFO("Calculated normalisation of PDF = " << norm ); } - int currentSize = output.size(); for( auto& event : events ){ if( event.prob > norm * gRandom->Uniform() ) output.push_back( event ); if( output.size() >= N ) break ; } - INFO( "size = " << output.size() << " / " << N << " efficiency = " << 100 * double(output.size()-currentSize)/double(m_blockSize) ); + double efficiency = 100 * double(output.size() - currentSize )/double(m_blockSize); + double time = std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); + pb.print( double(output.size()) / double(N), " ε[gen] = " + mysprintf("%.2f",efficiency) + "% , " + std::to_string(int(time/1000.)) + " seconds" ); + currentSize = output.size(); } auto psi_q = PhaseSpace(m_headPhsp); auto beta = [](const Event& event, const size_t&j){ return sqrt( event[4*j+0]*event[4*j+0] + event[4*j+1]*event[4*j+1] + event[4*j+2]*event[4*j+2] )/event[4*j+3] ; }; - auto p = [](const Event& event, const size_t&j){ return std::make_tuple( event[4*j+0], event[4*j+1], event[4*j+2] ) ; }; + auto p = [](const Event& event, const size_t&j){ return std::make_tuple(event[4*j+0], event[4*j+1], event[4*j+2]); }; for( auto& event : output ){ auto psi_event = psi_q.makeEvent(); boost( event.signal, p(psi_event,0), beta(psi_event,0)); boost( event.tag , p(psi_event,1), beta(psi_event,1)); } - pc.stop(); - INFO("Requested: " << N << " events t=" << pc << "[ms]"); + double time = std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); + pb.finish(); + INFO("Requested: " << N << " events t=" << time/1000 << "[ms]"); return output; } DTEventList generatePHSP(const size_t& N, const bool& eval=true){ @@ -191,6 +197,7 @@ template class Psi3770 { return output; } double rho() { + if( m_ignoreQc ) return 1; double withQC=0; double withoutQC =0; DTEventList evts = generatePHSP(m_blockSize, false); @@ -210,22 +217,22 @@ int main( int argc, char** argv ) auto time_wall = std::chrono::high_resolution_clock::now(); auto time = std::clock(); size_t hwt = std::thread::hardware_concurrency(); - size_t nThreads = NamedParameter("nCores" , hwt , "Number of threads to use"); - double luminosity = NamedParameter("Luminosity" , 818.3 , "Luminosity to generate. Defaults to CLEO-c integrated luminosity."); - size_t nEvents = NamedParameter("nEvents" , 0 , "Can also generate a fixed number of events per tag, if unspecified use the CLEO-c integrated luminosity."); - size_t seed = NamedParameter("Seed" , 0 , "Random seed to use."); - bool poissonYield = NamedParameter("PoissonYield" , true , "Flag to include Poisson fluctuations in expected yields (only if nEvents is not specified)"); - double crossSection = NamedParameter("CrossSection" , 3.26 * 1000 , "Cross section for e⁺e⁻ → Ψ(3770) → DD'"); - std::string output = NamedParameter("Output" , "ToyMC.root" , "File containing output events"); + size_t nThreads = NamedParameter("nCores" , hwt , "Number of threads to use"); + double luminosity = NamedParameter("Luminosity" , 818.3 , "Luminosity to generate. Defaults to CLEO-c integrated luminosity."); + size_t nEvents = NamedParameter("nEvents" , 0 , "Can also generate a fixed number of events per tag, if unspecified use the CLEO-c integrated luminosity."); + size_t seed = NamedParameter("Seed" , 0 , "Random seed to use."); + bool poissonYield = NamedParameter("PoissonYield", true , "Flag to include Poisson fluctuations in expected yields (only if nEvents is not specified)"); + double crossSection = NamedParameter("CrossSection", 3.26 * 1000 , "Cross section for e⁺e⁻ → Ψ(3770) → DD'"); + std::string output = NamedParameter("Output" , "ToyMC.root", "File containing output events"); auto pNames = NamedParameter("EventType" , "" , "EventType to generate, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(); auto tags = NamedParameter("TagTypes" , std::string(), "Vector of opposite side tags to generate, in the format \033[3m outputTreeName decayDescriptor \033[0m.").getVector(); gRandom = new TRandom3(seed); #ifdef _OPENMP - omp_set_num_threads( nThreads ); - INFO("Setting " << nThreads << " fixed threads for OpenMP"); - omp_set_dynamic(0); + omp_set_num_threads( nThreads ); + INFO("Setting " << nThreads << " fixed threads for OpenMP"); + omp_set_dynamic(0); #endif MinuitParameterSet MPS; MPS.loadFromStream(); @@ -241,7 +248,7 @@ int main( int argc, char** argv ) auto tokens = split(tag, ' '); EventType type = Particle(tokens[1], {}, false).eventType(); double yield_noQC = yc(luminosity,signalType,type,true); - auto generator = Psi3770(models, signalType, type) ; + auto generator = Psi3770(models, signalType, type); double rho = generator.rho(); double yield = nEvents; if( nEvents == 0 && poissonYield ) yield = gRandom->Poisson(yield_noQC*rho); @@ -352,6 +359,7 @@ std::string DTEventList::particleName(const AmpGen::EventType& type, const size_ if( count.second == 1 ) return programatic_name(type[j]); return programatic_name(type[j])+std::to_string(count.first); } + TTree* DTEventList::tree(const std::string& name) { DTEvent tmp(at(0).signal, at(0).tag); @@ -361,7 +369,8 @@ TTree* DTEventList::tree(const std::string& name) ids_tag(m_tagType.size()); TTree* outputTree = new TTree(name.c_str(),name.c_str()); - for(size_t i = 0 ; i < m_sigType.size(); ++i ){ + for(size_t i = 0 ; i < m_sigType.size(); ++i ) + { outputTree->Branch((particleName(m_sigType, i)+"_PX").c_str(), &tmp.signal[4*i+0]); outputTree->Branch((particleName(m_sigType, i)+"_PY").c_str(), &tmp.signal[4*i+1]); outputTree->Branch((particleName(m_sigType, i)+"_PZ").c_str(), &tmp.signal[4*i+2]); @@ -369,7 +378,9 @@ TTree* DTEventList::tree(const std::string& name) outputTree->Branch((particleName(m_sigType, i)+"_ID").c_str(), &id_sig[i]); ids_sig[i] = ParticlePropertiesList::get( m_sigType[i] )->pdgID(); } - for(size_t i = 0 ; i < m_tagType.size(); ++i ){ + + for(size_t i = 0 ; i < m_tagType.size(); ++i ) + { outputTree->Branch(("Tag_"+particleName(m_tagType, i)+"_PX").c_str(), &tmp.tag[4*i+0]); outputTree->Branch(("Tag_"+particleName(m_tagType, i)+"_PY").c_str(), &tmp.tag[4*i+1]); outputTree->Branch(("Tag_"+particleName(m_tagType, i)+"_PZ").c_str(), &tmp.tag[4*i+2]); diff --git a/examples/SignalOnlyFitter.cpp b/examples/SignalOnlyFitter.cpp index 2f2a230b0ae..0b9ab9e25b2 100644 --- a/examples/SignalOnlyFitter.cpp +++ b/examples/SignalOnlyFitter.cpp @@ -47,6 +47,7 @@ int main( int argc, char* argv[] ) then the default value, and then the help string that will be printed if --h is specified as an option. */ std::string dataFile = NamedParameter("DataSample", "" , "Name of file containing data sample to fit." ); + std::string intFile = NamedParameter("IntegrationSample","" , "Name of file containing events to use for MC integration."); std::string logFile = NamedParameter("LogFile" , "Fitter.log", "Name of the output log file"); std::string plotFile = NamedParameter("Plots" , "plots.root", "Name of the output plot file"); @@ -99,7 +100,7 @@ int main( int argc, char* argv[] ) /* Generate events to normalise the PDF with. This can also be loaded from a file, which will be the case when efficiency variations are included. Default number of normalisation events is 5 million. */ - EventList eventsMC = Generator<>(evtType, &rndm).generate(5e6); + EventList eventsMC = intFile == "" ? Generator<>(evtType, &rndm).generate(5e6) : EventList(intFile, evtType, GetGenPdf(true)); sig.setMC( eventsMC ); diff --git a/src/ASTResolver.cpp b/src/ASTResolver.cpp index c48f5d7fe0f..6e308309e16 100644 --- a/src/ASTResolver.cpp +++ b/src/ASTResolver.cpp @@ -14,30 +14,30 @@ using namespace AmpGen; ASTResolver::ASTResolver(const std::map& evtMap, const MinuitParameterSet* mps ) : - evtMap(evtMap), - mps(mps), - nParameters(0) + m_evtMap(evtMap), + m_mps(mps), + m_nParameters(0) { - enable_cuda = NamedParameter("UseCUDA",false); - enable_compileTimeConstants = NamedParameter("ASTResolver::CompileTimeConstants", false); + m_enable_cuda = NamedParameter("UseCUDA",false); + m_enable_compileTimeConstants = NamedParameter("ASTResolver::CompileTimeConstants", false); } bool ASTResolver::hasSubExpressions() const { - return subTrees.size() != 0; + return m_subTrees.size() != 0; } void ASTResolver::reduceSubTrees() { - subTrees.clear(); - for( auto& t : tempTrees ){ + m_subTrees.clear(); + for( auto& t : m_tempTrees ){ auto expr = t.first->m_expression; uint64_t key = t.first->key(); - if( subTrees.count( key ) == 0 ){ - subTrees[ key ] = t.first->m_expression ; + if( m_subTrees.count( key ) == 0 ){ + m_subTrees[ key ] = t.first->m_expression ; } } - tempTrees.clear(); + m_tempTrees.clear(); } std::vector> ASTResolver::getOrderedSubExpressions( const Expression& expression ) @@ -48,7 +48,7 @@ std::vector> ASTResolver::getOrderedSubExpression do { reduceSubTrees(); bool verbose = false; - for( auto& st : subTrees ) { + for( auto& st : m_subTrees ) { st.second.resolve( *this ); auto stack_pos = used_functions.find( st.first ); if ( stack_pos == used_functions.end() ) { @@ -73,8 +73,8 @@ std::vector> ASTResolver::getOrderedSubExpression template <> void ASTResolver::resolve( const SubTree& subTree ) { - if( tempTrees.count( &subTree ) != 0 ) return; - tempTrees[&subTree] = 1; + if( m_tempTrees.count( &subTree ) != 0 ) return; + m_tempTrees[&subTree] = 1; } template <> void ASTResolver::resolve( const Spline& spline ) @@ -84,17 +84,17 @@ template <> void ASTResolver::resolve( const Spline& spline ) addResolvedParameter( &spline, address ); addResolvedParameter( spline.m_points.top().get(), address ); auto splineTransfer = dynamic_cast( m_cacheFunctions[spline.m_name].get() ); - if( mps == nullptr ) ERROR("Fix me!"); + if( m_mps == nullptr ) ERROR("Fix me!"); for( unsigned int i = 0 ; i < spline.m_nKnots; ++i ) - splineTransfer->set(i, mps->find(spline.m_name+"::"+std::to_string(i)) ); + splineTransfer->set(i, m_mps->find(spline.m_name+"::"+std::to_string(i)) ); } template <> void ASTResolver::resolve( const Parameter& parameter ) { if( m_resolvedParameters.count(¶meter) != 0 || parameter.isResolved() ) return; - auto res = evtMap.find(parameter.name()); - if( res != evtMap.end() ){ - if( enable_cuda ) { + auto res = m_evtMap.find(parameter.name()); + if( res != m_evtMap.end() ){ + if( m_enable_cuda ) { size_t t = res->second; std::string it = ""; if( t % 3 == 0 ) it = ".x"; @@ -111,10 +111,10 @@ template <> void ASTResolver::resolve( const Parameter& parameter ) } return; } - else if( mps != nullptr ){ - auto it = mps->find(parameter.name()); + else if( m_mps != nullptr ){ + auto it = m_mps->find(parameter.name()); if( it != nullptr ){ - if( enable_compileTimeConstants && + if( m_enable_compileTimeConstants && it->iFixInit() == MinuitParameter::Flag::CompileTimeConstant ){ addResolvedParameter( ¶meter, "("+std::to_string(it->mean()) +")" ); } @@ -122,7 +122,7 @@ template <> void ASTResolver::resolve( const Parameter& parameter ) return; } } - else if( enable_compileTimeConstants ){ + else if( m_enable_compileTimeConstants ){ addResolvedParameter( ¶meter, std::to_string( parameter.defaultValue() ) ); return; } @@ -133,8 +133,8 @@ template <> void ASTResolver::resolve( const Parameter& parameter ) template <> void ASTResolver::resolve(const MinuitParameterLink& parameter) { if( m_resolvedParameters.count(¶meter) != 0 ) return; - if( mps == nullptr ) return; - auto it = mps->find(parameter.name()); + if( m_mps == nullptr ) return; + auto it = m_mps->find(parameter.name()); if( it == nullptr ) return; addResolvedParameter(¶meter, addCacheFunction( parameter.name(),it)); } diff --git a/src/BinDT.cpp b/src/BinDT.cpp index 992c7ef482a..fe78d92e7be 100644 --- a/src/BinDT.cpp +++ b/src/BinDT.cpp @@ -90,10 +90,10 @@ BinDT::BinDT( const ArgumentPack& args ) m_maxDepth = args.getArg( 999 ); m_dim = args.getArg( 5 ); m_functors = args.getArg( makeDefaultFunctors() ).val; - auto fname = args.getArg(); - if ( fname.name != "" ) { - std::ifstream stream( fname.name, fname.mode | std::ios::in ); - readFromStream( stream ); + auto fname = args.getArg("").val; + if ( fname != "" ) { + auto stream = std::ifstream(fname); + readFromStream(stream); } } @@ -342,17 +342,6 @@ void BinDT::Decision::setChildren( std::shared_ptr l, std::shared_ptrm_parent = this; } -uint32_t BinDT::AddressCompressor::operator[]( const void* ptr ) -{ - auto it = elements.find( ptr ); - if ( it != elements.end() ) - return it->second; - else { - elements[ptr] = counter++; - return elements[ptr]; - } -} - BinDT::EndNode::EndNode( const unsigned int& no, const unsigned int& binNumber ) : m_voxNumber( no ), m_binNumber( binNumber ) {} @@ -366,7 +355,6 @@ void BinDT::EndNode::serialize( std::ostream& stream ) const const BinDT::EndNode* BinDT::Decision::operator()( const double* evt ) const { -// INFO( m_index << " " << m_value << " " << *(evt+m_index)); return *( evt + m_index ) < m_value ? ( *m_right )( evt ) : ( *m_left )( evt ); } diff --git a/src/CacheTransfer.cpp b/src/CacheTransfer.cpp index 04f9edae16b..0c8aa6166a2 100644 --- a/src/CacheTransfer.cpp +++ b/src/CacheTransfer.cpp @@ -9,25 +9,38 @@ using namespace AmpGen; -CacheTransfer::CacheTransfer( const unsigned int& address, const double& value, const size_t& size ) : - m_address(address), m_value(value), m_size(size) {} +CacheTransfer::CacheTransfer() = default; + +CacheTransfer::CacheTransfer( const size_t& address, const double& value, const size_t& size ) : + m_address(address), + m_size(size), + m_value(value) +{ +} void CacheTransfer::transfer( CompiledExpressionBase* destination ) { destination->setExternal(m_value, m_address); } -void CacheTransfer::print() const { INFO( m_address << " " << m_value ) ; } + +void CacheTransfer::print() const +{ + INFO( m_address << " " << m_value ) ; +} void ParameterTransfer::transfer( CompiledExpressionBase* destination ) { destination->setExternal( m_source->mean(), m_address ); } -CacheTransfer::CacheTransfer() : m_address( 0 ), m_value( 0 ) {} - -ParameterTransfer::ParameterTransfer( const unsigned int& address, MinuitParameter* source ) - : m_address( address ), m_source( source ) +ParameterTransfer::ParameterTransfer( const size_t& address, MinuitParameter* source ) + : CacheTransfer(address, source->mean(), 1), + m_source( source ) { } -void ParameterTransfer::print() const { std::cout << this << " " << m_source->name() << " " << m_address << std::endl; INFO( "Source: " << m_source->name() << " address = " << m_address ); } +void ParameterTransfer::print() const +{ + std::cout << this << " " << m_source->name() << " " << m_address << std::endl; + INFO( "Source: " << m_source->name() << " address = " << m_address ); +} diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index d9cc735028e..da8f4d3e231 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -26,12 +26,13 @@ #include "AmpGen/ThreadPool.h" #include "AmpGen/ProfileClock.h" -#ifdef __USE_OPENMP__ +#ifdef _OPENMP #include #endif using namespace AmpGen; -CoherentSum::CoherentSum(){} +CoherentSum::CoherentSum() = default; + CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, const std::string& prefix ) : m_protoAmplitudes( mps ) , m_evtType( type ) @@ -86,7 +87,6 @@ void CoherentSum::prepare() ProfileClock clockIntegral; if ( m_integrator.isReady()) updateNorms( changedPdfIndices ); else if ( m_verbosity ) WARNING( "No simulated sample specified for " << this ); - m_norm = norm(); if ( m_verbosity && printed ) { clockIntegral.stop(); @@ -362,4 +362,3 @@ complex_t CoherentSum::getVal( const Event& evt, const std::vector value += m_matrixElements[i].coefficient * evt.getCache( cacheAddresses[i] ); return value; } - diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index 5edb7ee0049..7785bf54882 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -56,13 +56,11 @@ CompiledExpressionBase::CompiledExpressionBase( const Expression& expression, m_name( name ), m_progName( programatic_name(name) ), m_db(db), - m_evtMap(evtMapping), - m_readyFlag(nullptr) {} + m_evtMap(evtMapping) {} CompiledExpressionBase::CompiledExpressionBase( const std::string& name ) : m_name( name ), - m_progName( programatic_name(name) ), - m_readyFlag(nullptr) {} + m_progName( programatic_name(name) ) {} std::string CompiledExpressionBase::name() const { return m_name; } std::string CompiledExpressionBase::progName() const { return m_progName; } @@ -118,16 +116,9 @@ std::ostream& AmpGen::operator<<( std::ostream& os, const CompiledExpressionBase return os; } -void CompiledExpressionBase::compile(const std::string& fname, const bool& wait ) +void CompiledExpressionBase::compile(const std::string& fname) { - if(!wait){ - m_readyFlag = new std::shared_future( ThreadPool::schedule([this,fname](){ - CompilerWrapper().compile(*this,fname); - return true;} ) ); - } - else { - CompilerWrapper(false).compile(*this,fname ); - } + CompilerWrapper(false).compile(*this,fname ); } void CompiledExpressionBase::addDebug( std::ostream& stream ) const diff --git a/src/DalitzIntegrator.cpp b/src/DalitzIntegrator.cpp index 320ce538c70..aab7a7f8cd3 100644 --- a/src/DalitzIntegrator.cpp +++ b/src/DalitzIntegrator.cpp @@ -174,14 +174,11 @@ TH2D* DalitzIntegrator::makePlot( const std::function& fc const std::string& name, const size_t& nSamples ) { auto plot = projection.plot(); - double event[12]; - for ( unsigned int i = 0; i < 12; ++i ) event[i] = 0; - Event evtCache( 12 ); + Event event( 12 ); for ( unsigned int i = 0; i < nSamples; ++i ) { sqCo pos = {gRandom->Uniform(), gRandom->Uniform()}; setEvent( pos, event ); - evtCache.set( event ); - auto obs_cos = projection( evtCache ); + auto obs_cos = projection( event ); plot->Fill( obs_cos.first, obs_cos.second, J( pos ) * fcn( event ) ); } return plot; diff --git a/src/FitFraction.cpp b/src/FitFraction.cpp index 8ad62890824..65a1cec41bf 100644 --- a/src/FitFraction.cpp +++ b/src/FitFraction.cpp @@ -11,15 +11,12 @@ using namespace AmpGen; -FitFraction::FitFraction( const std::string& line, const EventType& evtType ) +FitFraction::FitFraction( const std::string& line ) { auto tokens = split( line, ' ' ); m_name = tokens[1]; m_value = stod( tokens[2] ); m_error = stod( tokens[3] ); - if ( evtType.size() != 0 ) { - std::vector finalStates = evtType.finalStates(); - } } std::shared_ptr FitFraction::particle() const { return std::make_shared( m_name ); } diff --git a/src/FitResult.cpp b/src/FitResult.cpp index 3c5253adf7c..5d593e6b06a 100644 --- a/src/FitResult.cpp +++ b/src/FitResult.cpp @@ -23,50 +23,84 @@ using namespace AmpGen; -FitResult::FitResult( const std::string& filename, const EventType& evtType ) +FitResult::FitResult() = default; + +FitResult::FitResult( const FitResult& other ) + : m_mps( std::make_shared( *other.mps() ) ) + , m_chi2( other.chi2() ) + , m_LL( other.LL() ) + , m_nBins( other.nBins() ) + , m_nParam( other.nParam() ) + , m_status( other.status() ) + , m_observables( other.observables() ) + , m_fitFractions( other.fitFractions() ) { - m_eventType = evtType; - m_fitted = readFile( filename ); + m_covarianceMatrix.ResizeTo( other.cov().GetNrows(), other.cov().GetNcols() ); + m_covarianceMatrix = other.cov(); } -std::string FitResult::getLastLine( std::ifstream& in ) const +FitResult::FitResult( const std::string& filename ) : + m_mps( std::make_shared() ) { - std::string line; - while ( in >> std::ws && std::getline( in, line ) ) ; - return line; + m_fitted = readFile( filename ); } -bool FitResult::readFile( const std::string& fname ) +FitResult::FitResult( const Minimiser& mini ) { - std::ifstream CHECK( fname ); - if ( !CHECK.is_open() || CHECK.peek() == std::ifstream::traits_type::eof() ) { - return false; + m_mps = std::make_shared( *mini.parSet() ); + m_LL = mini.FCN(); + auto M = mini.covMatrixFull(); + m_covarianceMatrix.ResizeTo( M.GetNcols(), M.GetNrows() ); + m_covarianceMatrix = M; + m_status = mini.status(); + m_nParam = 0; + for (size_t i = 0; i < m_mps->size(); ++i ) { + if ( m_mps->at(i)->iFixInit() == 0 ) m_nParam++; + m_covMapping[ m_mps->at(i)->name() ] = i; } - if ( getLastLine( CHECK ) != "End Log" ) { - ERROR( "File not properly close " << fname ); - return false; +} + +FitResult::FitResult( const MinuitParameterSet& mps, const TMatrixD& covMini ) : + m_mps( std::make_shared( mps ) ) +{ + if ( int( mps.size() ) != covMini.GetNcols() ) { + ERROR( "Minuit parameter set size does not match covariance matrix size!" ); } - CHECK.close(); - std::vector parameterLines; + m_covarianceMatrix.ResizeTo( covMini.GetNcols(), covMini.GetNrows() ); + m_covarianceMatrix = covMini; + for (size_t i = 0; i < m_mps->size(); ++i ) { + if ( m_mps->at(i)->iFixInit() == 0 ) m_nParam++; + } +} - processFile( fname, [this, ¶meterLines]( auto& line ) { +bool FitResult::readFile( const std::string& fname ) +{ + std::ifstream checkIsClosed( fname ); + if ( !checkIsClosed.is_open() + || checkIsClosed.peek() == std::ifstream::traits_type::eof() ) return false; + checkIsClosed.close(); + auto lines = vectorFromFile(fname); + if( *lines.rbegin() != "End Log" ){ + ERROR("File not properly closed: " << *lines.rbegin() ); + return false; + } + std::vector parameterLines; + for( auto& line : lines ){ const std::string name = split( line, ' ' )[0]; if ( name == "Parameter" ) parameterLines.push_back( line ); - else if ( name == "FitQuality" ) this->setFitQuality( line ); - else if ( name == "FitFraction" ) this->m_fitFractions.emplace_back( line, m_eventType ); - else if ( name == "Observable" ) this->addToObservables( line ); - } ); - + else if ( name == "FitQuality" ) this->setFitQuality( line ); + else if ( name == "FitFraction" ) this->m_fitFractions.emplace_back(line); + else if ( name == "Observable" ) this->addToObservables( line ); + } size_t nParameters = parameterLines.size(); m_covarianceMatrix.ResizeTo( parameterLines.size(), parameterLines.size() ); - m_mps = std::make_shared(); for (size_t i = 0; i < nParameters; ++i ) { + INFO("parsing line: " << parameterLines[i] ); auto tokens = split( parameterLines[i], ' ' ); m_covMapping[tokens[1]] = i; m_mps->add( new MinuitParameter( tokens[1], MinuitParameter::Flag(stoi( tokens[2] ) ), stod( tokens[3] ), stod( tokens[4] ), 0, 0 ) ); for (size_t j = 0; j < nParameters; ++j ) m_covarianceMatrix( i, j ) = stod( tokens[5 + j] ); } - return true; } @@ -75,8 +109,8 @@ void FitResult::setFitQuality( const std::string& line ) auto tokens = split( line, ' ' ); bool status=true; if( tokens.size() != 6 ){ - WARNING("Cannot pass FitQuality line: " << line ); - return; + WARNING("Cannot pass FitQuality line: " << line ); + return; } m_chi2 = lexical_cast( tokens[1] , status ); m_nBins = lexical_cast( tokens[2] , status ); @@ -84,6 +118,7 @@ void FitResult::setFitQuality( const std::string& line ) m_LL = lexical_cast( tokens[4] , status ); m_status = lexical_cast ( tokens[5] , status ); } + void FitResult::addToObservables( const std::string& line ) { auto tokens = split( line, ' ' ); @@ -96,55 +131,22 @@ void FitResult::writeToFile( const std::string& fname ) { std::ofstream outlog; outlog.open( fname ); - for (size_t i = 0; i < (size_t)m_covarianceMatrix.GetNrows(); ++i ) { auto param = m_mps->at(i); outlog << "Parameter" - << " " << param->name() << " " << param->iFixInit() << " " << param->mean() << " " - << m_mps->at(i)->err() << " "; + << " " << param->name() << " " << param->iFixInit() << " " << param->mean() << " " + << m_mps->at(i)->err() << " "; for (size_t j = 0; j < (size_t)m_covarianceMatrix.GetNcols(); ++j ) outlog << m_covarianceMatrix[i][j] << " "; outlog << std::endl; } outlog << std::setprecision( 8 ); - outlog << "FitQuality " << m_chi2 << " " << m_nBins << " " << m_nParam << " " << m_LL << " " << m_status << "\n"; - for ( auto& p : m_fitFractions ) { - outlog << "FitFraction " << p.name() << " " << p.val() << " " << p.err() << "\n"; - } - for ( auto& ob : m_observables ) { - outlog << "Observable " << ob.first << " " << ob.second << "\n"; - } + outlog << "FitQuality " << m_chi2 << " " << m_nBins << " " << m_nParam << " " << m_LL << " " << m_status << "\n"; + for ( auto& f : m_fitFractions ) outlog << "FitFraction " << f.name() << " " << f.val() << " " << f.err() << "\n"; + for ( auto& o : m_observables ) outlog << "Observable " << o.first << " " << o.second << "\n"; outlog << "End Log\n"; outlog.close(); } -FitResult::FitResult( const Minimiser& mini ) -{ - m_mps = std::make_shared( *mini.parSet() ); - m_LL = mini.FCN(); - auto M = mini.covMatrixFull(); - m_covarianceMatrix.ResizeTo( M.GetNcols(), M.GetNrows() ); - m_covarianceMatrix = M; - m_status = mini.status(); - m_nParam = 0; - for (size_t i = 0; i < m_mps->size(); ++i ) { - if ( m_mps->at(i)->iFixInit() == 0 ) m_nParam++; - m_covMapping[ m_mps->at(i)->name() ] = i; - } -} - -FitResult::FitResult( const MinuitParameterSet& mps, const TMatrixD& covMini ) : FitResult() -{ - m_mps = std::make_shared( mps ); - if ( int( mps.size() ) != covMini.GetNcols() ) { - ERROR( "Minuit parameter set size does not match covariance matrix size!" ); - } - m_covarianceMatrix.ResizeTo( covMini.GetNcols(), covMini.GetNrows() ); - m_covarianceMatrix = covMini; - for (size_t i = 0; i < m_mps->size(); ++i ) { - if ( m_mps->at(i)->iFixInit() == 0 ) m_nParam++; - } -} - void FitResult::print() const { INFO( "Chi2 per bin = " << m_chi2 / m_nBins ); @@ -153,29 +155,14 @@ void FitResult::print() const INFO( "Fit Status = " << m_status ); } -FitResult::FitResult( const FitResult& other ) - : m_chi2( other.chi2() ) - , m_LL( other.LL() ) - , m_nBins( other.nBins() ) - , m_nParam( other.nParam() ) - , m_status( other.status() ) - , m_eventType( other.eventType() ) - , m_observables( other.observables() ) - , m_fitFractions( other.fitFractions() ) - , m_mps( std::make_shared( *other.mps() ) ) -{ - m_covarianceMatrix.ResizeTo( other.cov().GetNrows(), other.cov().GetNcols() ); - m_covarianceMatrix = other.cov(); -} - -std::vector FitResult::getParameters() const +std::vector FitResult::parameters() const { std::vector params( m_mps->size() ); std::copy( m_mps->begin(), m_mps->end(), params.begin() ); return params; } -std::vector FitResult::getFloating( const bool& extended ) const +std::vector FitResult::floating( const bool& extended ) const { std::vector floating; for ( auto& param : *m_mps ) { @@ -194,7 +181,7 @@ TMatrixD FitResult::getReducedCovariance( const bool& extended ) const TMatrixD reducedCov( floating_indices.size(), floating_indices.size() ); if ( int( floating_indices.size() ) > m_covarianceMatrix.GetNrows() ) { ERROR( "Looking for more floating indices than real indices: " << m_covarianceMatrix.GetNrows() << " " - << floating_indices.size() ); + << floating_indices.size() ); return reducedCov; } for ( unsigned int i = 0; i < floating_indices.size(); ++i ) { @@ -207,7 +194,7 @@ TMatrixD FitResult::getReducedCovariance( const bool& extended ) const LinearErrorPropagator FitResult::getErrorPropagator( const bool& extended ) const { - return LinearErrorPropagator( getReducedCovariance( extended ), getFloating( extended ) ); + return LinearErrorPropagator( getReducedCovariance( extended ), floating( extended ) ); } void FitResult::addChi2( const double& chi2, const double& nBins ) @@ -216,4 +203,39 @@ void FitResult::addChi2( const double& chi2, const double& nBins ) m_nBins = nBins; } -void FitResult::addFractions( const std::vector& fractions ) { m_fitFractions = fractions; } +void FitResult::addFractions( const std::vector& fractions ) +{ + m_fitFractions = fractions; +} + +double FitResult::chi2() const { return m_chi2; } +double FitResult::LL() const { return m_LL; } +int FitResult::status() const { return m_status; } +int FitResult::nParam() const { return m_nParam; } +int FitResult::nBins() const { return m_nBins; } + +std::map FitResult::observables() const { return m_observables; } +std::shared_ptr FitResult::mps() const { return m_mps; } + +double FitResult::dof() const { return m_nBins - m_nParam - 1; } +std::vector FitResult::fitFractions() const { return m_fitFractions; } +TMatrixD FitResult::cov() const { return m_covarianceMatrix; } +double FitResult::cov( const size_t& x, const size_t& y ) const { return m_covarianceMatrix( x, y ); } +double FitResult::cov( const std::string& x, const std::string& y ) const { return m_covarianceMatrix( m_covMapping.at(x), m_covMapping.at(y) ); } + +void FitResult::addFraction( const std::string& name, const double& frac, const double& err ) +{ + m_fitFractions.emplace_back( name, frac, err ); +} +void FitResult::clearFitFractions() { m_fitFractions.clear(); } +void FitResult::setCov( const size_t& x, const size_t& y, const double& F ) { m_covarianceMatrix( x, y ) = F; } +double FitResult::correlation( const std::string& x, const std::string& y ) const +{ + auto tx = m_covMapping.find(x); + auto ty = m_covMapping.find(y); + if( tx == m_covMapping.end() || ty == m_covMapping.end() ){ + ERROR("Parameter not found: " << x << ", " << y ); + return -1; + } + return cov(tx->second, ty->second)/sqrt(cov(tx->second, tx->second)*cov(ty->second, ty->second)); +} diff --git a/src/IncoherentSum.cpp b/src/IncoherentSum.cpp index 1df5e034969..68ca1ede38f 100644 --- a/src/IncoherentSum.cpp +++ b/src/IncoherentSum.cpp @@ -40,15 +40,12 @@ double IncoherentSum::norm( const Bilinears& norms ) const void IncoherentSum::prepare() { if ( m_weightParam != nullptr ) m_weight = m_weightParam->mean(); - if ( m_isConstant && m_prepareCalls != 0 ) return; - transferParameters(); for ( auto& mE : m_matrixElements ) { auto& pdf = mE.pdf; pdf.prepare(); if ( m_prepareCalls != 0 && !pdf.hasExternalsChanged() ) continue; - if ( m_prepareCalls == 0 && m_events != nullptr ) mE.addressData = m_events->registerExpression( pdf ); @@ -83,17 +80,17 @@ std::vector IncoherentSum::fitFractions( const LinearErrorPropagato for ( auto& p : outputFractions ) INFO(p); return outputFractions; } -double IncoherentSum::getVal( const Event& evt ) const -{ + +double IncoherentSum::prob( const Event& evt ) const +{ + return m_weight * prob_unnormalised(evt) / m_norm; +} + +double IncoherentSum::prob_unnormalised( const Event& evt ) const +{ double value( 0. ); for ( auto& mE : m_matrixElements ) { value += std::norm( mE.coefficient * evt.getCache( mE.addressData ) ); } return value; } -double IncoherentSum::operator()( const Event& evt ) const { return prob( evt ); } -double IncoherentSum::prob( const Event& evt ) const -{ - return m_weight * getVal( evt ) / m_norm; -} -double IncoherentSum::prob_unnormalised( const Event& evt ) const { return getVal( evt ); } diff --git a/src/Lineshapes/GLASS.cpp b/src/Lineshapes/GLASS.cpp index 64075e13256..3b0bc80f94a 100644 --- a/src/Lineshapes/GLASS.cpp +++ b/src/Lineshapes/GLASS.cpp @@ -12,33 +12,40 @@ using namespace AmpGen::fcn; DEFINE_LINESHAPE( GLASS ) { - WARNING("GLASS lineshape does not work as expected"); - const auto props = ParticlePropertiesList::get( particleName ); - Expression mass = Parameter( particleName + "_mass", props->mass() ); - Expression width0 = Parameter( particleName + "_width", props->width() ); - Expression s0 = mass*mass; - Expression a = Parameter( particleName + "::GLASS::a", 2.07 ); - Expression r = Parameter( particleName + "::GLASS::r", 3.32 ); - Expression phi_R = Parameter( particleName + "::GLASS::phiR", 0.00 ); - Expression phi_F = Parameter( particleName + "::GLASS::phiF", 0.00 ); - Expression R = Parameter( particleName + "::GLASS::R", 1.00 ); - Expression F = Parameter( particleName + "::GLASS::F", 1.00 ); - Expression q2 = Q2(s, s1, s2); - Expression q20 = Q2(s0, s1, s2); - Expression q = safe_sqrt( q2 ); - Expression rho = q/sqrt(s); - Expression rho0 = sqrt(q20)/mass; - Expression gamma = width0 * rho / rho0; - Expression dF = make_cse(M_PI*phi_F/180. + atan(2*a*q/(2 + a*r*q2))); - Expression dR = make_cse(M_PI*phi_R/180. + atan(mass*gamma / (s0 - s))); - Expression i = Constant(0,1); - ADD_DEBUG(s, dbexpressions ); - ADD_DEBUG(s0, dbexpressions ); - ADD_DEBUG(dF, dbexpressions ); - ADD_DEBUG(dR, dbexpressions ); - ADD_DEBUG(phi_F, dbexpressions ); - ADD_DEBUG(phi_R, dbexpressions ); - ADD_DEBUG(gamma, dbexpressions ); - - return R*sin(dR)*exp(i*dR)*exp(2*i*dF) + F*sin(dF)*exp(i*dF); + const auto props = ParticlePropertiesList::get( particleName ); + Expression mass = Parameter( particleName + "_mass", props->mass() ); + Expression width0 = Parameter( particleName + "_width", props->width() ); + Expression s0 = mass*mass; + Expression a = Parameter( particleName + "::GLASS::a", 2.07 ); + Expression r = Parameter( particleName + "::GLASS::r", 3.32 ); + Expression phiR = Parameter( particleName + "::GLASS::phiR", 0.00 ); + Expression phiF = Parameter( particleName + "::GLASS::phiF", 0.00 ); + Expression R = Parameter( particleName + "::GLASS::R", 1.00 ); + Expression F = Parameter( particleName + "::GLASS::F", 1.00 ); + Expression q2 = Q2(s, s1, s2); + Expression q20 = Q2(s0, s1, s2); + Expression q = safe_sqrt( q2 ); + Expression i = Constant(0,1); + Expression mR = mass; + Expression pR = sqrt( q20 ); + Expression gammaR = width0; + + auto g = width0 * mass * sqrt( q2 / ( q20 * s ) ); + auto propagator_relativistic_BreitWigner = 1./(mass*mass - s - i*mass*g); + auto cot_deltaF = 1.0/(a*q) + 0.5*r*q; + auto qcot_deltaF = 1.0/a + 0.5*r*q2; + auto expi2deltaF = (qcot_deltaF + i * q) / (qcot_deltaF - i * q); + auto resonant_term_T = R * exp( i*(phiR + 2*phiF) ) * propagator_relativistic_BreitWigner * mR * gammaR * mR / pR * expi2deltaF; + auto non_resonant_term_F = F * exp( i*phiF ) * (cos(phiF) + cot_deltaF * sin(phiF)) * sqrt(s) / (qcot_deltaF -i * q); + auto LASS_contribution = non_resonant_term_F + resonant_term_T; + + ADD_DEBUG( g , dbexpressions); + ADD_DEBUG( propagator_relativistic_BreitWigner, dbexpressions); + ADD_DEBUG( cot_deltaF , dbexpressions); + ADD_DEBUG( qcot_deltaF , dbexpressions); + ADD_DEBUG( expi2deltaF , dbexpressions); + ADD_DEBUG( resonant_term_T , dbexpressions); + ADD_DEBUG( non_resonant_term_F , dbexpressions); + ADD_DEBUG( LASS_contribution , dbexpressions); + return LASS_contribution; } diff --git a/src/Lineshapes/LASS.cpp b/src/Lineshapes/LASS.cpp index 1a6404df832..1d6acb358ef 100644 --- a/src/Lineshapes/LASS.cpp +++ b/src/Lineshapes/LASS.cpp @@ -14,7 +14,6 @@ DEFINE_LINESHAPE( LASS ) { const auto props = ParticlePropertiesList::get( particleName ); Expression mass = Parameter( particleName + "_mass", props->mass() ); - Expression radius = Parameter( particleName + "_radius", props->radius() ); Expression width0 = Parameter( particleName + "_width", props->width() ); Expression s0 = mass*mass; Expression a = Parameter( "LASS::a", 2.07 ); @@ -35,6 +34,7 @@ DEFINE_LINESHAPE( LASS ) Expression bw = ( mass * width0 ) / ( rho0 * ( s0 -s -i*mass*gamma ) ); Expression nrPhaseShift = ( 2 + a * r * q2 + i * 2*a*q ) / ( 2+a*r*q2 - i*2*a*q ); Expression NR = 2*a*sqrt(s)/( 2 + a*r*q*q -2*i*a*q ); + ADD_DEBUG(s, dbexpressions ); ADD_DEBUG(nrPhaseShift*bw, dbexpressions ); ADD_DEBUG(NR, dbexpressions ); ADD_DEBUG(NR + bw*nrPhaseShift, dbexpressions ); diff --git a/src/Lineshapes/kMatrix.cpp b/src/Lineshapes/kMatrix.cpp index f6063bead25..a47db3aa13f 100644 --- a/src/Lineshapes/kMatrix.cpp +++ b/src/Lineshapes/kMatrix.cpp @@ -25,7 +25,7 @@ Expression AmpGen::phsp_twoBody( const Expression& s, const double& m0, const do Expression AmpGen::phsp_fourPi( const Expression& s ) { // Parameterisation of the 4pi phase-space taken from Laura++ (https://laura.hepforge.org/ or Ref. https://arxiv.org/abs/1711.09854) - double mPiPlus( 0.139570 ); + double mPiPlus = 0.139570; Expression rho_4pi = pol( s, {0.00051, -0.01933, 0.13851, -0.20840, -0.29744, 0.13655, 1.07885} ); return Ternary( s > 1, phsp_twoBody( s, 2 * mPiPlus, 2 * mPiPlus ), rho_4pi ); } @@ -93,7 +93,7 @@ DEFINE_LINESHAPE( kMatrix ) double mPiPlus = 0.139570; double mKPlus = 0.493677; double mEta = 0.547862; - double mEtap = 0.96778; + double mEtap = 0.967780; Expression sA0 = Parameter( "sA0", -0.15 ); Expression sA = Parameter( "sA", 1.0 ); diff --git a/src/Minimiser.cpp b/src/Minimiser.cpp index a0d84924bea..e0d4514c540 100644 --- a/src/Minimiser.cpp +++ b/src/Minimiser.cpp @@ -8,7 +8,6 @@ #include #include - #include "AmpGen/IExtendLikelihood.h" #include "AmpGen/MinuitParameter.h" #include "AmpGen/MinuitParameterSet.h" @@ -35,11 +34,11 @@ double Minimiser::operator()( const double* xx ) for(size_t i = 0; i < m_mapping.size(); ++i ) { m_parSet->at( m_mapping[i] )->setCurrentFitVal( xx[i] ); } - double LL = m_theFunction(); + double LL = m_theFunction() ; for ( auto& extendTerm : m_extendedTerms ) { LL -= 2 * extendTerm->getVal(); } - return LL; + return LL - m_ll_zero; } void Minimiser::GradientTest() @@ -59,6 +58,7 @@ void Minimiser::GradientTest() parameter->setCurrentFitVal( m ); } } + double Minimiser::FCN() const { return m_theFunction(); } void Minimiser::prepare() @@ -67,6 +67,7 @@ void Minimiser::prepare() size_t maxCalls = NamedParameter( "Minimiser::MaxCalls" , 100000); double tolerance = NamedParameter( "Minimiser::Tolerance" , 1); m_printLevel = NamedParameter( "Minimiser::PrintLevel", 4); + m_normalise = NamedParameter( "Minimiser::Normalise",false); if ( m_minimiser != nullptr ) delete m_minimiser; m_minimiser = new Minuit2::Minuit2Minimizer(algorithm.c_str() ); DEBUG( "Error definition = " << m_minimiser->ErrorDef() ); @@ -98,7 +99,7 @@ void Minimiser::prepare() bool Minimiser::doFit() { - m_lastPrint = 999; + if( m_normalise ) m_ll_zero = m_theFunction(); ROOT::Math::Functor f( *this, m_nParams ); for (size_t i = 0; i < m_mapping.size(); ++i ) { MinuitParameter* par = m_parSet->at( m_mapping[i] ); @@ -106,7 +107,6 @@ bool Minimiser::doFit() if ( par->minInit() != 0 || par->maxInit() != 0 ) m_minimiser->SetVariableLimits( i, par->minInit(), par->maxInit() ); } - m_minimiser->SetFunction( f ); m_minimiser->Minimize(); for (size_t i = 0; i < m_nParams; ++i ) { diff --git a/src/MinuitParameter.cpp b/src/MinuitParameter.cpp index 8edc615e4a9..bf51b7509f1 100644 --- a/src/MinuitParameter.cpp +++ b/src/MinuitParameter.cpp @@ -16,6 +16,13 @@ MinuitParameter::MinuitParameter( const std::string& name, const MinuitParameter resetToInit(); } +MinuitParameter::MinuitParameter( const std::string& name, const double& mean, const double& step, const double& mi, const double& ma ) + : MinuitParameter(name, MinuitParameter::Flag::Float, m_meanInit, m_stepInit, m_minInit, m_maxInit ) +{ + DEBUG( "Building parameter : " << name ); + resetToInit(); +} + MinuitParameter::Flag MinuitParameter::iFixInit() const { return m_iFixInit; } double MinuitParameter::meanInit() const { return m_meanInit; } diff --git a/src/ParticleProperties.cpp b/src/ParticleProperties.cpp index 680a9c4c744..ae80229b683 100644 --- a/src/ParticleProperties.cpp +++ b/src/ParticleProperties.cpp @@ -179,7 +179,8 @@ std::string ParticleProperties::spinName() const { return "?"; } -const ParticleProperties* ParticleProperties::get( const std::string& name, const bool& quiet ){ +const ParticleProperties* ParticleProperties::get( const std::string& name, const bool& quiet ) +{ return ParticlePropertiesList::get( name, quiet ); } diff --git a/src/ProgressBar.cpp b/src/ProgressBar.cpp new file mode 100644 index 00000000000..84ba994f132 --- /dev/null +++ b/src/ProgressBar.cpp @@ -0,0 +1,38 @@ +#include "AmpGen/ProgressBar.h" +#include "AmpGen/MsgService.h" + +#include +#include +#include +using namespace AmpGen; + +ProgressBar::ProgressBar(const size_t& width, const std::string& context) + : m_width(width), + m_lastPercent(-1), + m_context(context) {} + +ProgressBar::~ProgressBar(){ + if( !m_finished ) finish(); +} + +void ProgressBar::print(const double& percentage, const std::string& message) +{ + int lpad = int(percentage * m_width); + int val = int(percentage * 100); + if( val == m_lastPercent ) return; + m_lastPercent = val; + std::cout << "\r\033[2;34m" << std::left << std::setw( FCNNAMELENGTH ) << m_context << " INFO " << "\033[0m"; + std::cout << "Completed: " << std::right << std::setw(3) << val << "% " << "["; + std::fill_n(std::ostream_iterator(std::cout), lpad, '|'); + std::fill_n(std::ostream_iterator(std::cout), m_width-lpad, ' '); + std::cout << "]"; + std::cout << message; + m_lastMessage = message; + fflush (stdout); +} + +void ProgressBar::finish(){ + print(1,m_lastMessage); + std::cout << std::endl; + m_finished = true; +} diff --git a/src/Spline.cpp b/src/Spline.cpp index e85f614cea3..fbb9aa01ef7 100644 --- a/src/Spline.cpp +++ b/src/Spline.cpp @@ -80,24 +80,21 @@ void SplineTransfer::print() const { INFO( "Source: " << m_parameters[0]->name() SplineTransfer::SplineTransfer() = default; SplineTransfer::SplineTransfer( const SplineTransfer& other ) - : CacheTransfer() + : CacheTransfer(other.m_address, other.m_value, other.m_size) , m_transferMatrix( other.m_transferMatrix ) , m_parameters( other.m_parameters ) , m_min( other.m_min ) , m_max( other.m_max ) - , m_address( other.m_address ) { } -SplineTransfer::SplineTransfer( const unsigned int& address, const unsigned int& N, const double& min, const double& max ) - : CacheTransfer() +SplineTransfer::SplineTransfer( const size_t& address, const unsigned int& N, const double& min, const double& max ) + : CacheTransfer(address) , m_transferMatrix( TMatrixD( N - 2, N - 2 ) ) , m_parameters( N, nullptr ) , m_nKnots(N) , m_min( min ) , m_max( max ) - , m_address( address ) - { unsigned int size = N - 2; TMatrixD M(size, size); @@ -129,7 +126,6 @@ void SplineTransfer::set( const unsigned int& N, const double& value ) m_parameters[N] = new MinuitParameter("dumb",MinuitParameter::Fix,value,0); } -void SplineTransfer::setAddress( const unsigned int& address ) { m_address = ( address ); } void SplineTransfer::transfer( CompiledExpressionBase* destination ) { unsigned int size = m_parameters.size() - 2; diff --git a/src/ThreadPool.cpp b/src/ThreadPool.cpp index 05fa274eb37..b0489cf116c 100644 --- a/src/ThreadPool.cpp +++ b/src/ThreadPool.cpp @@ -6,10 +6,7 @@ using namespace AmpGen; -ThreadPool* ThreadPool::gThreadPool = nullptr; -size_t ThreadPool::nThreads = 10; - -ThreadPool::ThreadPool(const size_t& nt) : m_stop(false) +ThreadPool::ThreadPool(const size_t& nt) { for ( size_t i = 0; i < nt; ++i ) m_workers.emplace_back( [this] { diff --git a/src/ThreeBodyCalculators.cpp b/src/ThreeBodyCalculators.cpp index 66dfe18de13..a484da7eeb0 100644 --- a/src/ThreeBodyCalculators.cpp +++ b/src/ThreeBodyCalculators.cpp @@ -263,16 +263,13 @@ void ThreeBodyCalculator::makePlots(const double& mass, const size_t& x, const s { auto& sq = m_widths[0].integrator; auto& evtType = m_widths[0].type; - if( mass != -1 ) evtType.setMotherMass( mass ); auto& fcs = m_widths[0].totalWidth; auto projection_operators = evtType.defaultProjections( 500 ); int points = NamedParameter( "nPoints", 50000000 ); sq.setMother( evtType.motherMass() ); prepare(); auto fcn = [&](const double* evt) { return std::real(fcs(evt)); }; - sq.makePlot( fcn, Projection2D( projection_operators[x], projection_operators[y] ), "s01_vs_s02", points )->Write(); - } void ThreeBodyCalculator::debug( const double& m, const double& theta ) From 13a871dd4b22a67b378c7b6b0e20fadb5eea6a21 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 10 Jun 2019 22:44:15 +0200 Subject: [PATCH 073/250] add FixedLibPdf models (for D0->KsPiPi) to QcGenerator, fixes in doxgen --- AmpGen/CoherentSum.h | 49 +++++++++------- AmpGen/EventType.h | 14 ++--- AmpGen/IncoherentSum.h | 10 ++-- AmpGen/Lineshapes.h | 20 +++---- AmpGen/Particle.h | 74 ++++++++++++------------ apps/ConvertToSourceCode.cpp | 42 +++++++++++++- apps/Debugger.cpp | 11 ++-- examples/QcGenerator.cpp | 105 ++++++++++++++++++++++++----------- src/CoherentSum.cpp | 4 +- src/Lineshapes/GLASS.cpp | 62 +++++++++------------ 10 files changed, 236 insertions(+), 155 deletions(-) diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index 4f4ee8f0ce8..a3048971f4e 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -1,5 +1,5 @@ -#ifndef AMPGEN_FASTCOHERENTSUM_H -#define AMPGEN_FASTCOHERENTSUM_H +#ifndef AMPGEN_COHERENTSUM_H +#define AMPGEN_COHERENTSUM_H #include #include @@ -27,8 +27,15 @@ namespace AmpGen class Particle; /** @class CoherentSum - @brief An coherent sum of amplitudes - Fuck you doxygen. + @brief A coherent sum of amplitudes + + An coherent sum of resonant contributions, where at a position in phase-space @f$\psi@f$, + the (unnormalised) probability density is given by + @f[ + \mathcal{P}(\psi) = \left| \sum_{i} g_i \mathcal{A}_i(\psi) \right|^2, + @f] + where @f$\mathcal{P}(\psi)@f$ is the probability, @f$g_i@f$ is the coupling to an isobar channel, + and @f$\mathcal{A}_i(\psi)@f$ is the amplitude of the ith channel. */ class CoherentSum { @@ -80,23 +87,23 @@ namespace AmpGen protected: std::vector> m_matrixElements; ///< Vector of (expanded) matrix elements - Bilinears m_normalisations; ///< Normalisation integrals - AmplitudeRules m_protoAmplitudes; ///< Proto amplitudes from user rule-set - Integrator<10> m_integrator; ///< Integral dispatch tool (with default unroll = 10) - TransitionMatrix m_total; ///< Total Matrix Element - EventList* m_events = {nullptr}; ///< Data events to evaluate PDF on - EventType m_evtType; ///< Final state for this amplitude - MinuitParameter* m_weightParam = {nullptr}; ///< Weight parameter (i.e. the normalised yield) - size_t m_prepareCalls = {0}; ///< Number of times prepare has been called - size_t m_lastPrint = {0}; ///< Last time verbose PDF info was printed - size_t m_printFreq = {0}; ///< Frequency to print verbose PDF info - double m_weight = {1}; ///< Weight number (i.e. the normalised yield) - double m_norm = {0}; ///< Normalisation integral - bool m_isConstant = {false}; ///< Flag for a constant PDF - bool m_dbThis = {false}; ///< Flag to generate amplitude level debugging - bool m_verbosity = {false}; ///< Flag for verbose printing - std::string m_objCache = {""}; ///< Directory that contains (cached) amplitude objects - std::string m_prefix = {""}; ///< Prefix for matrix elements + Bilinears m_normalisations; ///< Normalisation integrals + AmplitudeRules m_protoAmplitudes; ///< Proto amplitudes from user rule-set + Integrator<10> m_integrator; ///< Integral dispatch tool (with default unroll = 10) + TransitionMatrix m_total; ///< Total Matrix Element + EventList* m_events = {nullptr}; ///< Data events to evaluate PDF on + EventType m_evtType; ///< Final state for this amplitude + MinuitParameter* m_weightParam = {nullptr}; ///< Weight parameter (i.e. the normalised yield) + size_t m_prepareCalls = {0}; ///< Number of times prepare has been called + size_t m_lastPrint = {0}; ///< Last time verbose PDF info was printed + size_t m_printFreq = {0}; ///< Frequency to print verbose PDF info + double m_weight = {1}; ///< Weight number (i.e. the normalised yield) + double m_norm = {0}; ///< Normalisation integral + bool m_isConstant = {false}; ///< Flag for a constant PDF + bool m_dbThis = {false}; ///< Flag to generate amplitude level debugging + bool m_verbosity = {false}; ///< Flag for verbose printing + std::string m_objCache = {""}; ///< Directory that contains (cached) amplitude objects + std::string m_prefix = {""}; ///< Prefix for matrix elements void addMatrixElement( std::pair& particleWithCoupling, const MinuitParameterSet& mps ); }; } // namespace AmpGen diff --git a/AmpGen/EventType.h b/AmpGen/EventType.h index 25f4edd11e5..19c05ee53a1 100644 --- a/AmpGen/EventType.h +++ b/AmpGen/EventType.h @@ -19,21 +19,21 @@ namespace AmpGen class EventType { public: - /// @constructor Default constructor + /// Default constructor EventType() = default; - /// @constructor Takes a list of particles, beginning with the head of the decay and + /// Takes a list of particles, beginning with the head of the decay and /// then then final state particles, and a flag as to whether to include time dependence. EventType( const std::vector&, const bool& isTD = false ); - /// @function Returns the CP-conjugated event type. Can also require that only the initial/ + /// Returns the CP-conjugated event type. Can also require that only the initial/ /// final state is conjugated. By default, conjugates both. EventType conj( const bool& headOnly = 0, const bool& dontConjHead = 0 ) const; - /// @function Returns the event format, that matches between expressions and the names used in Particle. + /// Returns the event format, that matches between expressions and the names used in Particle. std::map getEventFormat( const bool& outputNames = false ) const; - /// @function Counts the number of particles in this event type with + /// Counts the number of particles in this event type with /// the same name as the index'th name. std::pair count(const size_t& index) const; std::pair minmax( const std::vector& indices, bool isGeV = false ) const; @@ -59,10 +59,10 @@ namespace AmpGen void extendEventType( const std::string& branch ); - /// @function Functor to randomly symmetrise data of this event type, using the Fisher-Yates shuffle. + /// Functor to randomly symmetrise data of this event type, using the Fisher-Yates shuffle. std::function symmetriser() const; - /// @function Calculates the number of spin indices associated with the initial and final state, i.e. the rank of the relevant transition matrix. + /// Calculates the number of spin indices associated with the initial and final state, i.e. the rank of the relevant transition matrix. std::pair dim() const; private: diff --git a/AmpGen/IncoherentSum.h b/AmpGen/IncoherentSum.h index e60c34bb443..70479a3717c 100644 --- a/AmpGen/IncoherentSum.h +++ b/AmpGen/IncoherentSum.h @@ -29,25 +29,25 @@ namespace AmpGen @f] where @f$\mathcal{P}(\psi)@f$ is the probability, @f$g_i@f$ is the coupling to an isobar channel, and @f$\mathcal{A}_i(\psi)@f$ is the amplitude of the ith channel. - what's going on ??? + I dont know whats going on? */ class IncoherentSum : public CoherentSum { public: - /** @constructor Constructs an incoherentSum from the type of event this is expected to describe, + /** Constructs an incoherentSum from the type of event this is expected to describe, and a set of parameters that are expected to be able to describe it. @param eventType The type of event that this PDF should describe @param mps The parameter set of couplings, masses, etc. @param prefix Prefix required for the ``head'' decays for this event type. */ IncoherentSum(const EventType& eventType, const AmpGen::MinuitParameterSet& mps, const std::string& prefix = "Inco"); - /// @function Evaluates the normalised probability for an event. + /// Evaluates the normalised probability for an event. double prob( const Event& evt ) const; - /// @function Calculates the unnormalised probability for an event. + /// Calculates the unnormalised probability for an event. double prob_unnormalised( const Event& evt ) const; - /** @function Returns the normalisation for this PDF, given by + /** Returns the normalisation for this PDF, given by @f[ \mathcal{N} = \int d\psi \varepsilon(\psi) \mathcal{P}(\psi) \approx \sum_i \frac{\mathcal{P}(\psi_i)}{\mathcal{P}^\prime(\psi_i)} @f] diff --git a/AmpGen/Lineshapes.h b/AmpGen/Lineshapes.h index 0ad6b22634c..e4334613381 100644 --- a/AmpGen/Lineshapes.h +++ b/AmpGen/Lineshapes.h @@ -251,16 +251,16 @@ namespace AmpGen @f] that is, the 'resonant' and 'nonresonant' phases of the LASS formulation with additional 'proudction' phases @f$ \phi_R @f$ and @f$\phi_F @f$, and production couplings @f$R, F@f$. One of the production couplings can typically be fixed to 1, normally the resonant coupling, @f$R @f$. - Parameter | User name | Description - -----------------------|--------------------------------------|------------------------------------------------------------------------ - @f$m@f$ | particleName_mass | Breit-Wigner mass of the resonant component, defined as energy at which the self-energy of the resonance is purely imaginary (defaults to value in PDG)
- @f$\Gamma_0@f$ | particleName_width | Breit-Wigner width of the resonant component, defined as the width of resonance at the Breit-Wigner mass
- @f$a@f$ | particleName::GLASS::a | Scattering length of the nonresonant component, defaults to @f$2.07\mathrm{G\kern -0.1em eV}^{-1}@f$ - @f$r@f$ | particleName::GLASS::r | Effective interaction length of the nonresonant component, defaults to @f$3.32\mathrm{G\kern -0.1em eV}^{-1}@f$ - @f$\phi_R@f$ | particleName::GLASS::phiR | Additional production phase of the resonant component, defaults to @f$0^{\mathrm{o}}@f$, measured in degrees. - @f$\phi_F@f$ | particleName::GLASS::phiF | Additional production phase of the nonresonant component, defaults to @f$0^{\mathrm{o}}@f$, measured in degrees. - @f$R@f$ | particleName::GLASS::R | Additional production coupling of the resonant component, defaults to @f$1@f$. - @f$F@f$ | particleName::GLASS::F | Additional production coupling of the nonresonant component, defaults to @f$1@f$. + Parameter | User name | Description + -----------------------|----------------------------------|------------------------------------------------------------------------ + @f$m@f$ | particleName_mass | Breit-Wigner mass of the resonant component, defined as energy at which the self-energy of the resonance is purely imaginary (defaults to value in PDG)
+ @f$\Gamma_0@f$ | particleName_width | Breit-Wigner width of the resonant component, defined as the width of resonance at the Breit-Wigner mass
+ @f$a@f$ | particleNameGLASSa | Scattering length of the nonresonant component, defaults to @f$2.07\mathrm{G\kern -0.1em eV}^{-1}@f$ + @f$r@f$ | particleNameGLASSr | Effective interaction length of the nonresonant component, defaults to @f$3.32\mathrm{G\kern -0.1em eV}^{-1}@f$ + @f$\phi_R@f$ | particleNameGLASSphiR | Additional production phase of the resonant component, defaults to @f$0^{\mathrm{o}}@f$, measured in degrees. + @f$\phi_F@f$ | particleNameGLASSphiF | Additional production phase of the nonresonant component, defaults to @f$0^{\mathrm{o}}@f$, measured in degrees. + @f$R@f$ | particleNameGLASSR | Additional production coupling of the resonant component, defaults to @f$1@f$. + @f$F@f$ | particleNameGLASSF | Additional production coupling of the nonresonant component, defaults to @f$1@f$. */ DECLARE_LINESHAPE(GLASS); diff --git a/AmpGen/Particle.h b/AmpGen/Particle.h index 02e68812ce7..50b410359f9 100644 --- a/AmpGen/Particle.h +++ b/AmpGen/Particle.h @@ -97,34 +97,34 @@ namespace AmpGen class Particle { public: - /// @constructor default constructor + /// Default Constructor Particle(); - /// @constructor Constructor that takes a pair of other particles (i.e. this particle's decay products) as arguments and looks up the properties of this particle using the particle name. + /// Constructor that takes a pair of other particles (i.e. this particle's decay products) as arguments and looks up the properties of this particle using the particle name. Particle( const std::string& name, const Particle& p1, const Particle& p2 ); - /// @constructor Constructor that takes a pair of other particles (i.e. this particle's decay products) as arguments and looks up the properties of this particle using the PDG MC ID. + /// Constructor that takes a pair of other particles (i.e. this particle's decay products) as arguments and looks up the properties of this particle using the PDG MC ID. Particle( const int& pdg_id, const Particle& p1, const Particle& p2 ); - /// @constructor Constructor by name and with an index to match to the event type + /// Constructor by name and with an index to match to the event type Particle( const std::string& name, const unsigned int& index ); - /// @constructor Constructor that takes a decay descriptor as an argument and a list of final state particles to match to the event type. Constructs the entire decay tree. + /// Constructor that takes a decay descriptor as an argument and a list of final state particles to match to the event type. Constructs the entire decay tree. Particle( const std::string& decayString, const std::vector& finalStates = {}, const bool& orderDaughters = true ); - /// @function (Quasi) Constructor that returns the (quasi)CP conjugated amplitude. The full behaviour of the amplitude is made more complicated by the ordering convention. + /// (Quasi) Constructor that returns the (quasi)CP conjugated amplitude. The full behaviour of the amplitude is made more complicated by the ordering convention. Particle conj(bool invertHead = true, bool reorder = true); - /// @function Set the orbital quantum number 'L' for this decay. + /// Set the orbital quantum number 'L' for this decay. void setOrbital( const unsigned int& orbital ); - /// @function Set the lineshape for the decay of this particle. + /// Set the lineshape for the decay of this particle. void setLineshape( const std::string& lineshape ); - /// @function Set the index'th daughter of this to particle. + /// Set the index'th daughter of this to particle. void setDaughter( const Particle& particle, const unsigned int& index ); - /// @function Set the flag to say this + /// Set the flag to say this void setTop( bool state = true ); void setIndex( const unsigned int& index, const bool& setOri = false ); void clearDecayProducts(); @@ -136,7 +136,7 @@ namespace AmpGen void addDaughter( const std::shared_ptr& particle ); void setPolarisationState( const int& state ); - /// @function Returns the range of orbital angular momentum between the decay products + /// Returns the range of orbital angular momentum between the decay products std::pair orbitalRange( const bool& converseParity = true ) const; std::vector> spinOrbitCouplings( const bool& conserveParity = true ) const; stdx::optional attribute(const std::string& key) const; @@ -161,83 +161,83 @@ namespace AmpGen unsigned int index() const; unsigned int originalIndex() const; - /// @function Name of the decaying particle. + /// Name of the decaying particle. std::string name() const; - /// @function Name of the propagator to use for the decay of this particle. + /// Name of the propagator to use for the decay of this particle. std::string lineshape() const; - /// @function Name of the (spin)vertex to use for the decay of this particle + /// Name of the (spin)vertex to use for the decay of this particle std::string vertexName() const; - /// @function The unique string (i.e. decay descriptor) that identifies this decay / + /// The unique string (i.e. decay descriptor) that identifies this decay / /// can be parsed to generate the decay tree. std::string uniqueString() const; - /// @function The descriptor that describes this decay / + /// The descriptor that describes this decay / /// that can be parsed to generate the decay tree and uniquely identify it. std::string decayDescriptor() const; - /// @function The string that describes the spin/orbital topology of this decay, + /// The string that describes the spin/orbital topology of this decay, /// i.e. replacing specific particle names with their spins. std::string topologicalString() const; - /// @function The string that describes the spin/orbit configuration of this decay. + /// The string that describes the spin/orbit configuration of this decay. std::string orbitalString() const; - /// @function Decay descriptor formatted as LaTeX for this decay. + /// Decay descriptor formatted as LaTeX for this decay. std::string texLabel( const bool& printHead = false, const bool& recurse=true ) const; - /// @function Returns the ``quasi'' CP Quantum number for this decay, see the Particle + /// Returns the ``quasi'' CP Quantum number for this decay, see the Particle int quasiCP() const; - /// @function Returns the C quantum number for this decay + /// Returns the C quantum number for this decay int C() const; - /// @function Return the eventType for this decay (i.e. the initial and final state particles) + /// Return the eventType for this decay (i.e. the initial and final state particles) EventType eventType() const; - /// @function Returns the indexth decay product of this particle + /// Returns the indexth decay product of this particle std::shared_ptr daughter( const size_t& index ); - /// @function Returns in indexth decay product of this particle (as constant) + /// Returns in indexth decay product of this particle (as constant) std::shared_ptr daughter( const size_t& index ) const; - /// @function Vector of decay products of this particle + /// Vector of decay products of this particle std::vector> daughters() const; - /// @function Get orderings of the final state that are identical to each other, i.e. those that only differ by exchanging identical particles. + /// Get orderings of the final state that are identical to each other, i.e. those that only differ by exchanging identical particles. std::vector> identicalDaughterOrderings() const; - /// @function Returns the final state particles for this decay process. + /// Returns the final state particles for this decay process. std::vector> getFinalStateParticles( const bool& sort = true ) const; - /// @function Calculate the particle tree only including quasi-stable processes, + /// Calculate the particle tree only including quasi-stable processes, /// i.e. only includes states with lifetimes > ParticleProperties::qsThreshold (default ~ 1 KeV ) Particle quasiStableTree() const; - /// @function Calculates the momentum sum of the decay products + /// Calculates the momentum sum of the decay products Tensor P() const; - /// @function Calculates the momentum difference between the decay products (only well defined for quasi two-body processes ) + /// Calculates the momentum difference between the decay products (only well defined for quasi two-body processes ) Tensor Q() const; - /// @function Calculates the spin tensor or generalised current for this particle + /// Calculates the spin tensor or generalised current for this particle Tensor spinTensor( DebugSymbols* db = nullptr ) const; - /// @function Calculates the polarisation vector / spinor etc. of this particle, used for the initial/final state particles + /// Calculates the polarisation vector / spinor etc. of this particle, used for the initial/final state particles Tensor externalSpinTensor(const int& polState, DebugSymbols* db = nullptr) const; - /// @function Calculates the invariant mass-squared of the mass of this particle + /// Calculates the invariant mass-squared of the mass of this particle Expression massSq() const; - /// @function Calculates the lineshape / propagator for this particle. + /// Calculates the lineshape / propagator for this particle. Expression propagator( DebugSymbols* db = nullptr ) const; - /// @function Calculates the total expression for this particle, including symmetrisation and the current polarisation state + /// Calculates the total expression for this particle, including symmetrisation and the current polarisation state Expression getExpression( DebugSymbols* db = nullptr, const unsigned int& index = 0 ); - /// @function Calculate the transition matrix for this decay + /// Calculate the transition matrix for this decay Tensor transitionMatrix( DebugSymbols* db = nullptr ); bool operator<( const Particle& other ); bool operator>( const Particle& other ); @@ -250,7 +250,7 @@ namespace AmpGen DifferentOrbital = ( 1<<3 ), DifferentPolarisation = ( 1<<4 ) }; - /// @function matches Check the matching between two decay chains, according to the MatchState enum. + /// matches Check the matching between two decay chains, according to the MatchState enum. unsigned int matches( const Particle& other ) const; private: diff --git a/apps/ConvertToSourceCode.cpp b/apps/ConvertToSourceCode.cpp index 5329b91bb6c..0896aeeb591 100644 --- a/apps/ConvertToSourceCode.cpp +++ b/apps/ConvertToSourceCode.cpp @@ -14,6 +14,8 @@ #include "AmpGen/Utilities.h" #include "AmpGen/ThreadPool.h" #include "AmpGen/Particle.h" +#include "AmpGen/ParticlePropertiesList.h" + #include "TRandom3.h" using namespace AmpGen; @@ -66,6 +68,37 @@ void create_integration_tests(T& pdf, unit_tests.close(); } +void invert( MinuitParameter* param, MinuitParameterSet& mps ) +{ + const std::string name = param->name(); + size_t pos = 0; + std::string new_name = name; + int sgn = 1; + std::string cartOrPolar = NamedParameter("CouplingConstant::Coordinates" ,"cartesian"); + + if( name.find("::") != std::string::npos ){ + pos = name.find("::"); + auto props = AmpGen::ParticlePropertiesList::get( name.substr(0,pos), true ); + if( props != 0 ) new_name = props->anti().name() + name.substr(pos); + } + else { + auto tokens=split(name,'_'); + std::string reOrIm = *tokens.rbegin(); + std::string name = tokens[0]; + if ( reOrIm == "Re" || reOrIm == "Im" ){ + Particle test = Particle(name).conj(); + if( cartOrPolar == "polar" ) sgn = reOrIm == "Re" ? test.quasiCP() : 1; + if( cartOrPolar == "cartesian" ) sgn = test.quasiCP(); + new_name = test.uniqueString() +"_"+reOrIm; + } + else if( tokens.size() == 2 ) { + auto props = AmpGen::ParticlePropertiesList::get( name ); + if( props != 0 ) new_name = props->anti().name() + "_" + tokens[1]; + } + } + mps.rename( param->name(), new_name ); + if( sgn == -1 ){ param->setInit( -1*param->mean() ) ; param->setCurrentFitVal( -1 * param->mean() );} +} template void generate_source(T& pdf, EventList& normEvents, const std::string& sourceFile, MinuitParameterSet& mps, const double& sf) { @@ -77,9 +110,7 @@ template void generate_source(T& pdf, EventList& normEvents, const std double pMax = 0 ; pdf.setEvents( normEvents ); pdf.prepare(); - normEvents[0].print(); - normEvents[0].printCache(); - INFO( pdf.prob_unnormalised( normEvents[0] ) ); + pdf.debug( normEvents[0] ); for ( auto& evt : normEvents ) { if( type == "PolarisedSum" ){ double px, py, pz; @@ -113,6 +144,11 @@ int main( int argc, char** argv ) AmpGen::MinuitParameterSet MPS; // MPS.loadFromStream(); + + if ( NamedParameter( "conj", false ) == true ) { + eventType = eventType.conj(true); + for ( auto& param : MPS ) invert( param, MPS ); + } Generator phsp( eventType ); TRandom3 rnd; diff --git a/apps/Debugger.cpp b/apps/Debugger.cpp index 4eb41281d5a..b2b7dbefc01 100644 --- a/apps/Debugger.cpp +++ b/apps/Debugger.cpp @@ -48,9 +48,11 @@ void invertParity( Event& event, const size_t& nParticles) void invert( MinuitParameter* param, MinuitParameterSet& mps ) { const std::string name = param->name(); - size_t pos=0; - std::string new_name = name; - int sgn=1; + size_t pos = 0; + std::string new_name = name; + int sgn = 1; + std::string cartOrPolar = NamedParameter("CouplingConstant::Coordinates" ,"cartesian"); + if( name.find("::") != std::string::npos ){ pos = name.find("::"); auto props = AmpGen::ParticlePropertiesList::get( name.substr(0,pos), true ); @@ -62,7 +64,8 @@ void invert( MinuitParameter* param, MinuitParameterSet& mps ) std::string name = tokens[0]; if ( reOrIm == "Re" || reOrIm == "Im" ){ Particle test = Particle(name).conj(); - sgn = reOrIm == "Re" ? test.quasiCP() : 1; + if( cartOrPolar == "polar" ) sgn = reOrIm == "Re" ? test.quasiCP() : 1; + if( cartOrPolar == "cartesian" ) sgn = test.quasiCP(); new_name = test.uniqueString() +"_"+reOrIm; } else if( tokens.size() == 2 ) { diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp index 33ff7459c76..528934572a0 100644 --- a/examples/QcGenerator.cpp +++ b/examples/QcGenerator.cpp @@ -12,14 +12,42 @@ #include #include #ifdef _OPENMP - #include - #include +#include +#include #endif using namespace AmpGen; using namespace std::complex_literals; -struct DTEvent { +class FixedLibPdf +{ + public: + FixedLibPdf() = default; + FixedLibPdf(const EventType& type, MinuitParameterSet& mps) : + FixedLibPdf(NamedParameter(type.decayDescriptor()+"::lib").getVal()) + { + INFO("Constructing: " << type << " flib = " <( handle, "AMP" ); + } + void prepare(){}; + void setEvents( AmpGen::EventList& evts ){}; + double prob_unnormalised( const AmpGen::Event& evt ) const { return std::norm(getValNoCache(evt)); } + complex_t getValNoCache( const AmpGen::Event& evt ) const { return amp(evt,+1); } + size_t size() { return 0; } + void reset( const bool& flag = false ){}; + private: + void* lib; + AmpGen::DynamicFCN amp; +}; + +struct DTEvent +{ AmpGen::Event signal; AmpGen::Event tag; double prob; @@ -32,7 +60,8 @@ struct DTEvent { } }; -struct DTEventList : public std::vector { +struct DTEventList : public std::vector +{ AmpGen::EventType m_sigType; AmpGen::EventType m_tagType; DTEventList( const AmpGen::EventType& signal, const AmpGen::EventType& tag ) : m_sigType(signal), m_tagType(tag) {} @@ -62,7 +91,7 @@ void add_CP_conjugate( MinuitParameterSet& mps ); template struct normalised_pdf { PDF pdf; complex_t norm; - normalised_pdf(){}; + normalised_pdf() = default; normalised_pdf(const EventType& type, MinuitParameterSet& mps, const DTYieldCalculator& yc) : pdf(type, mps) { ProfileClock pc; @@ -76,20 +105,22 @@ template struct normalised_pdf { norm = sqrt(yc.bf(type)/n); if( it != nullptr ) norm *= exp( 1i * it->mean() * M_PI/180. ); pc.stop(); - INFO("Time to construct: " << pc << "[ms], norm = " << norm ); + INFO(type << " Time to construct: " << pc << "[ms], norm = " << norm << " " << typeof() ); } complex_t operator()(const Event& event){ return norm * pdf.getValNoCache(event); } }; struct ModelStore { - MinuitParameterSet* mps; - DTYieldCalculator yieldCalculator; + MinuitParameterSet* mps; + DTYieldCalculator yieldCalculator; std::map> genericModels; + std::map> flibModels; ModelStore(MinuitParameterSet* mps, const DTYieldCalculator& yc) : mps(mps), yieldCalculator(yc) {} template normalised_pdf& get(const EventType& type, std::map>& container) { auto key = type.decayDescriptor(); - if( container.count(key) == 0 ) container[key] = normalised_pdf(type,*mps, yieldCalculator); + if( container.count(key) == 0 ) + container[key] = normalised_pdf(type, *mps, yieldCalculator); return container[key]; } template normalised_pdf& find(const EventType& type); @@ -115,7 +146,7 @@ template class Psi3770 { { double n1(0), n2(0), zR(0), zI(0); auto normEvents = Generator(type).generate(m_blockSize); - #pragma omp parallel for reduction(+:zR,zI,n1,n2) +#pragma omp parallel for reduction(+:zR,zI,n1,n2) for(size_t i = 0; i < m_blockSize; ++i){ auto p1 = t1(normEvents[i]); auto p2 = t2(normEvents[i]); @@ -192,7 +223,7 @@ template class Psi3770 { DTEventList generatePHSP(const size_t& N, const bool& eval=true){ DTEventList output( m_signalType, m_tagType ); for(size_t x = 0 ; x < m_blockSize; ++x) output.emplace_back( generatePhaseSpace() ); - #pragma omp parallel for +#pragma omp parallel for for(size_t i = 0 ; i < m_blockSize; ++i ) output[i].prob = P(output[i]); return output; } @@ -201,7 +232,7 @@ template class Psi3770 { double withQC=0; double withoutQC =0; DTEventList evts = generatePHSP(m_blockSize, false); - #pragma omp parallel for reduction(+:withQC,withoutQC) +#pragma omp parallel for reduction(+:withQC,withoutQC) for( size_t x = 0; x("CrossSection", 3.26 * 1000 , "Cross section for e⁺e⁻ → Ψ(3770) → DD'"); std::string output = NamedParameter("Output" , "ToyMC.root", "File containing output events"); auto pNames = NamedParameter("EventType" , "" - , "EventType to generate, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(); + , "EventType to generate, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(); auto tags = NamedParameter("TagTypes" , std::string(), "Vector of opposite side tags to generate, in the format \033[3m outputTreeName decayDescriptor \033[0m.").getVector(); - + gRandom = new TRandom3(seed); - #ifdef _OPENMP - omp_set_num_threads( nThreads ); - INFO("Setting " << nThreads << " fixed threads for OpenMP"); - omp_set_dynamic(0); - #endif +#ifdef _OPENMP + omp_set_num_threads( nThreads ); + INFO("Setting " << nThreads << " fixed threads for OpenMP"); + omp_set_dynamic(0); +#endif MinuitParameterSet MPS; MPS.loadFromStream(); add_CP_conjugate( MPS ); @@ -246,15 +277,28 @@ int main( int argc, char** argv ) ModelStore models(&MPS, yc); for( auto& tag : tags ){ auto tokens = split(tag, ' '); - EventType type = Particle(tokens[1], {}, false).eventType(); + auto tagParticle = Particle(tokens[1], {}, false); + EventType type = tagParticle.eventType(); double yield_noQC = yc(luminosity,signalType,type,true); - auto generator = Psi3770(models, signalType, type); - double rho = generator.rho(); - double yield = nEvents; - if( nEvents == 0 && poissonYield ) yield = gRandom->Poisson(yield_noQC*rho); - if( nEvents == 0 && !poissonYield ) yield = yield_noQC*rho; - INFO( "Tag = " << type << " Expected Yield [incoherent] = " << yield_noQC << " rho = " << rho << " requested = " << yield ); - generator.generate(yield).tree(tokens[0])->Write(); + std::string flib = NamedParameter( type.decayDescriptor() +"::lib", ""); + if( flib == "" ){ + auto generator = Psi3770(models, signalType, type); + double rho = generator.rho(); + double yield = nEvents; + if( nEvents == 0 && poissonYield ) yield = gRandom->Poisson(yield_noQC*rho); + if( nEvents == 0 && !poissonYield ) yield = yield_noQC*rho; + INFO( "Tag = " << type << " Expected Yield [incoherent] = " << yield_noQC << " rho = " << rho << " requested = " << yield ); + generator.generate(yield).tree(tokens[0])->Write(); + } + else { + auto generator = Psi3770(models, signalType, type); + double rho = generator.rho(); + double yield = nEvents; + if( nEvents == 0 && poissonYield ) yield = gRandom->Poisson(yield_noQC*rho); + if( nEvents == 0 && !poissonYield ) yield = yield_noQC*rho; + INFO( "Tag = " << type << " Expected Yield [incoherent] = " << yield_noQC << " rho = " << rho << " requested = " << yield ); + generator.generate(yield).tree(tokens[0])->Write(); + } } f->Close(); auto twall_end = std::chrono::high_resolution_clock::now(); @@ -264,7 +308,6 @@ int main( int argc, char** argv ) INFO( "CPU time = " << time_cpu ); } - void add_CP_conjugate( MinuitParameterSet& mps ) { std::vector tmp; @@ -320,7 +363,7 @@ double DTYieldCalculator::operator()(const double& lumi, if( t_signal == t_tag || t_signal == t_tag.conj(false,true) ) statisticalFactor = 1; auto signal = AmpGen::Particle(t_signal.decayDescriptor()).uniqueString(); auto tag = AmpGen::Particle(t_tag.decayDescriptor()).uniqueString(); - auto signalBar = AmpGen::replaceAll( signal, "D0","Dbar0"); + auto signalBar = AmpGen::replaceAll( signal, "D0", "Dbar0"); auto tagBar = AmpGen::replaceAll( tag, "D0", "Dbar0"); auto eff = [this](const std::string& tag) -> double { auto it = efficiencies.find(tag); if( it == efficiencies.end() ){ @@ -377,8 +420,7 @@ TTree* DTEventList::tree(const std::string& name) outputTree->Branch((particleName(m_sigType, i)+"_E").c_str(), &tmp.signal[4*i+3]); outputTree->Branch((particleName(m_sigType, i)+"_ID").c_str(), &id_sig[i]); ids_sig[i] = ParticlePropertiesList::get( m_sigType[i] )->pdgID(); - } - + } for(size_t i = 0 ; i < m_tagType.size(); ++i ) { outputTree->Branch(("Tag_"+particleName(m_tagType, i)+"_PX").c_str(), &tmp.tag[4*i+0]); @@ -402,4 +444,5 @@ TTree* DTEventList::tree(const std::string& name) } template <> normalised_pdf& ModelStore::find(const EventType& type){ return get(type, genericModels); } +template <> normalised_pdf& ModelStore::find(const EventType& type){ return get(type, flibModels); } diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index da8f4d3e231..2c962862bd8 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -127,8 +127,8 @@ void CoherentSum::debug( const Event& evt, const std::string& nameMustContain ) else for ( auto& pdf : m_matrixElements ) if ( pdf.pdf.name().find( nameMustContain ) != std::string::npos ) pdf.pdf.debug( evt ); - if( evt.cacheSize() != 0 ) - INFO( "Pdf = " << prob_unnormalised( evt ) ); + if( evt.cacheSize() != 0 ) INFO( "Pdf = " << prob_unnormalised( evt ) ); + INFO( "A(x) = " << getVal(evt) ); } std::vector CoherentSum::fitFractions(const LinearErrorPropagator& linProp) diff --git a/src/Lineshapes/GLASS.cpp b/src/Lineshapes/GLASS.cpp index 3b0bc80f94a..3fb68ec8929 100644 --- a/src/Lineshapes/GLASS.cpp +++ b/src/Lineshapes/GLASS.cpp @@ -12,40 +12,32 @@ using namespace AmpGen::fcn; DEFINE_LINESHAPE( GLASS ) { - const auto props = ParticlePropertiesList::get( particleName ); - Expression mass = Parameter( particleName + "_mass", props->mass() ); - Expression width0 = Parameter( particleName + "_width", props->width() ); - Expression s0 = mass*mass; - Expression a = Parameter( particleName + "::GLASS::a", 2.07 ); - Expression r = Parameter( particleName + "::GLASS::r", 3.32 ); - Expression phiR = Parameter( particleName + "::GLASS::phiR", 0.00 ); - Expression phiF = Parameter( particleName + "::GLASS::phiF", 0.00 ); - Expression R = Parameter( particleName + "::GLASS::R", 1.00 ); - Expression F = Parameter( particleName + "::GLASS::F", 1.00 ); - Expression q2 = Q2(s, s1, s2); - Expression q20 = Q2(s0, s1, s2); - Expression q = safe_sqrt( q2 ); - Expression i = Constant(0,1); - Expression mR = mass; - Expression pR = sqrt( q20 ); - Expression gammaR = width0; + const auto props = ParticlePropertiesList::get( particleName ); + const auto mass = Parameter( particleName + "_mass", props->mass() ); + const auto width0 = Parameter( particleName + "_width", props->width() ); + const auto s0 = mass*mass; + const auto a = Parameter( particleName + "::GLASS::a", 2.07 ); + const auto r = Parameter( particleName + "::GLASS::r", 3.32 ); + const auto phiR = Parameter( particleName + "::GLASS::phiR", 0.00 ); + const auto phiF = Parameter( particleName + "::GLASS::phiF", 0.00 ); + const auto R = Parameter( particleName + "::GLASS::R", 1.00 ); + const auto F = Parameter( particleName + "::GLASS::F", 1.00 ); + const auto q2 = Q2(s, s1, s2); + const auto q20 = Q2(s0, s1, s2); + const auto q = safe_sqrt( q2 ); + const auto i = Constant(0,1); + const auto width = width0 * mass * sqrt( q2 / ( q20 * s ) ); + const auto rbw = s0 * width0 /(sqrt(q20) * (mass*mass - s - i*mass*width )); + const auto den = ( 1.0 + 0.5*r*a*q2 - i * a * q); + const auto resTerm = R * exp( i*(phiR + 2*phiF) ) * rbw * ( 1.0 + 0.5*r*a*q2 + i * a * q ); + const auto nrTerm = F * exp( i*phiF ) * ( a * q * cos(phiF) + ( 1.0 + 0.5 * r * a * q2 ) * sin(phiF)) * sqrt(s) / q; + const auto total = (nrTerm + resTerm)/den; - auto g = width0 * mass * sqrt( q2 / ( q20 * s ) ); - auto propagator_relativistic_BreitWigner = 1./(mass*mass - s - i*mass*g); - auto cot_deltaF = 1.0/(a*q) + 0.5*r*q; - auto qcot_deltaF = 1.0/a + 0.5*r*q2; - auto expi2deltaF = (qcot_deltaF + i * q) / (qcot_deltaF - i * q); - auto resonant_term_T = R * exp( i*(phiR + 2*phiF) ) * propagator_relativistic_BreitWigner * mR * gammaR * mR / pR * expi2deltaF; - auto non_resonant_term_F = F * exp( i*phiF ) * (cos(phiF) + cot_deltaF * sin(phiF)) * sqrt(s) / (qcot_deltaF -i * q); - auto LASS_contribution = non_resonant_term_F + resonant_term_T; - - ADD_DEBUG( g , dbexpressions); - ADD_DEBUG( propagator_relativistic_BreitWigner, dbexpressions); - ADD_DEBUG( cot_deltaF , dbexpressions); - ADD_DEBUG( qcot_deltaF , dbexpressions); - ADD_DEBUG( expi2deltaF , dbexpressions); - ADD_DEBUG( resonant_term_T , dbexpressions); - ADD_DEBUG( non_resonant_term_F , dbexpressions); - ADD_DEBUG( LASS_contribution , dbexpressions); - return LASS_contribution; + ADD_DEBUG(width , dbexpressions); + ADD_DEBUG(rbw , dbexpressions); + ADD_DEBUG(den , dbexpressions); + ADD_DEBUG(resTerm/den, dbexpressions); + ADD_DEBUG(nrTerm/den , dbexpressions); + ADD_DEBUG(total , dbexpressions); + return total; } From 6f2efe18faaf81f0d198f1a02a8a806c59f5a8c2 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 18 Jun 2019 09:59:30 +0200 Subject: [PATCH 074/250] Add examples/SimFit, some bug fixes in README and minor clang warnings fixed --- AmpGen/EventList.h | 4 +- AmpGen/Integrator.h | 7 +-- AmpGen/Minimiser.h | 2 + AmpGen/PolarisedSum.h | 1 + AmpGen/SumPDF.h | 1 + README.md | 14 ++++-- doc/doxyfile | 2 +- examples/QcGenerator.cpp | 1 - examples/SimFit.cpp | 99 ++++++++++++++++++++++++++++++++++++++++ src/AmplitudeRules.cpp | 2 +- src/EventList.cpp | 14 +++++- src/PolarisedSum.cpp | 4 ++ src/Wigner.cpp | 2 - 13 files changed, 136 insertions(+), 17 deletions(-) create mode 100644 examples/SimFit.cpp diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 5534f71aef2..8a7fa280586 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -106,7 +106,7 @@ namespace AmpGen return size; } } - + template unsigned int extendEvent( const std::string& name, FUNCTOR func ) { @@ -126,7 +126,7 @@ namespace AmpGen ( *this )[i].setCache(fcn(getEvent(i)), index); } } - + void reserveCache(const size_t& index); TH2D* makeProjection( const Projection2D& projection, const ArgumentPack& args ); std::vector makeProjections( const std::vector& projections, const ArgumentPack& args ); diff --git a/AmpGen/Integrator.h b/AmpGen/Integrator.h index 44fc44707cf..195fe075d04 100644 --- a/AmpGen/Integrator.h +++ b/AmpGen/Integrator.h @@ -85,9 +85,10 @@ namespace AmpGen public: Integrator( EventList* events = nullptr ) : m_events( events ){} - double sampleNorm() { return m_events->norm(); } - bool isReady() const { return m_events != nullptr ; } - const EventList& events() const { return *m_events ; } + double sampleNorm() { return m_events->norm(); } + bool isReady() const { return m_events != nullptr; } + EventList& events() { return *m_events; } + const EventList& events() const { return *m_events; } template void addIntegral( const T1& f1, const T2& f2, const TransferFCN& tFunc ) { diff --git a/AmpGen/Minimiser.h b/AmpGen/Minimiser.h index 02772ab3a8b..e6940a6ab3a 100644 --- a/AmpGen/Minimiser.h +++ b/AmpGen/Minimiser.h @@ -10,6 +10,7 @@ #include "TMatrixTSym.h" +/** @cond PRIVATE */ namespace ROOT { namespace Math @@ -18,6 +19,7 @@ namespace ROOT } } class TGraph; +/** @endcode */ namespace AmpGen { diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index e9f7cf9225e..e161decdc1e 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -35,6 +35,7 @@ namespace AmpGen class PolarisedSum { public: + PolarisedSum() = default; PolarisedSum( const EventType& eventType, AmpGen::MinuitParameterSet& mps, const std::string& prefix="" ); void prepare(); void setEvents( AmpGen::EventList& events ); diff --git a/AmpGen/SumPDF.h b/AmpGen/SumPDF.h index dc9ab4e96e3..c85196c033a 100644 --- a/AmpGen/SumPDF.h +++ b/AmpGen/SumPDF.h @@ -23,6 +23,7 @@ namespace AmpGen class SumPDF { public: + SumPDF() = default; SumPDF( const TYPES&... _pdfs ) : m_pdfs( std::tuple( _pdfs... ) ) {} std::tuple m_pdfs; EventList* m_events; diff --git a/README.md b/README.md index 0ad406aab5a..9c31407efbd 100644 --- a/README.md +++ b/README.md @@ -69,13 +69,15 @@ is to specifically specify the location of the build tool for AmpGen's JIT: -DAMPGEN_CXX=$(which c++) ``` -##### CentOS7 +##### LXPLUS -In order to build stand-alone on CentOS7, you will need a valid development environment; the following line will work: +In order to build stand-alone on LXPLUS, you will need a valid development environment; the following line will work: ```shell -lb-run ROOT $SHELL +lb-run -c x86_64-centos7-gcc62-opt ROOT $SHELL ``` +Additionally, the ROOT versions installed on cvfms generally require C++17 support when building. + Several examples of usages of the library are included in the apps directory and are built alongside the library. All standalone programs can accept both options files and command line arguments. @@ -105,7 +107,7 @@ The decay products of a particle are enclosed within curly braces, for example K*(892)0{K+,pi-} ``` describes an excited vector kaon decaying into a charged kaon and pion. -For more details about the API for describing particle decays, see [AmpGen::Particle](https://tevans1260.gitlab.io/AmpGen/de/dd7/class_amp_gen_1_1_particle.html). +For more details about the API for describing particle decays, see [AmpGen::Particle](https://goofit.github.io/AmpGen/de/dd7/class_amp_gen_1_1_particle.html) The other numbers on the lines that describe the decays parameterise the coupling to this channel, either in terms of real and imaginary parts or an amplitude and a phase. Each parameter is specified in terms of three numbers: the _fix_ flag, the initial value, and the step size. @@ -131,6 +133,7 @@ Configuration can be split over multiple files by the using _Import_ keyword, fo ``` Import $AMPGENROOT/options/kMatrix.opt ``` + can be added to options file. Multiple user configuration files can also be specified by including multiple files on the command line. ## Applications @@ -171,6 +174,8 @@ activated by ``` which produces a large number of intermediate steps in the calculation of each amplitude, which are added to the calculation using the ADD_DEBUG and ADD_DEBUG_TENSOR macros in the code generation. For example, in src/Lineshapes/BW.cpp. +(n.b), if the model is a PolarisedSum, i.e. handles spin in the initial/final state, the flag PolarisedSum::Debug should be used instead of CoherentSum::Debug, in order +to generate all of the intermediate calculations of the amplitude. ### ConvertToSourceCode @@ -183,7 +188,6 @@ This can then be a compiled to a shared library using g++ -Ofast -shared -rdynamic --std=c++14 -fPIC MyFile.cpp -o MyFile.so ``` - ## Examples ### SignalOnlyFitter diff --git a/doc/doxyfile b/doc/doxyfile index c4db3d1ac5e..c7320a0781b 100644 --- a/doc/doxyfile +++ b/doc/doxyfile @@ -33,7 +33,7 @@ DOXYFILE_ENCODING = UTF-8 # The default value is: My Project. PROJECT_NAME = "AmpGen" -PROJECT_NUMBER = 1.1 +PROJECT_NUMBER = 1.2 PROJECT_BRIEF = PROJECT_LOGO = "figs/logo_small.png" LAYOUT_FILE = "DoxygenLayout.xml" diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp index 528934572a0..9bf6b02aecb 100644 --- a/examples/QcGenerator.cpp +++ b/examples/QcGenerator.cpp @@ -42,7 +42,6 @@ class FixedLibPdf size_t size() { return 0; } void reset( const bool& flag = false ){}; private: - void* lib; AmpGen::DynamicFCN amp; }; diff --git a/examples/SimFit.cpp b/examples/SimFit.cpp new file mode 100644 index 00000000000..824b769626c --- /dev/null +++ b/examples/SimFit.cpp @@ -0,0 +1,99 @@ +#include "AmpGen/Particle.h" +#include "AmpGen/CoherentSum.h" +#include "AmpGen/MsgService.h" +#include "AmpGen/SumPDF.h" +#include "AmpGen/FitResult.h" +#include "AmpGen/IExtendLikelihood.h" +#include "AmpGen/Minimiser.h" +#include "AmpGen/NamedParameter.h" +#include "AmpGen/Utilities.h" +#include "AmpGen/MinuitParameterSet.h" +#include "AmpGen/SimPDF.h" +#include "AmpGen/Kinematics.h" +#include "AmpGen/Generator.h" +#include "AmpGen/PolarisedSum.h" +#include + +#include "TRandom3.h" +#include "TFile.h" +#include "TTree.h" + +using namespace AmpGen; + +int main(int argc , char* argv[] ){ + OptionsParser::setArgs( argc, argv ); + + const auto pEventType = NamedParameter("EventType", std::vector(), + "EventType to fit, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(); + + const auto datasets = NamedParameter("Datasets","", + "List of data/simulated samples to fit, in the format \ + \033[3m data[0] sim[0] data[1] sim[1] ... \033[0m. \nIf a simulated sample is specified FLAT, uniformly generated phase-space events are used for integrals ").getVector(); + + const std::string logFile = NamedParameter("LogFile" , "Fitter.log", + "Name of the output log file"); + + const std::string plotFile = NamedParameter("Plots" , "plots.root", + "Name of the output plot file"); + + std::vector data; + std::vector mcs; + + #ifdef _OPENMP + size_t hwThreads = std::thread::hardware_concurrency(); + size_t usThreads = NamedParameter( "nCores", hwThreads, "Number of cores to use (OpenMP only)" ); + INFO("Using: " << usThreads << " / " << hwThreads << " threads" ); + omp_set_num_threads(usThreads); + omp_set_dynamic(0); + #endif + + INFO("Output : " << logFile << " plots = " << plotFile ); + + if( pEventType.size() == 0 ) FATAL("Must specify event format as EventType \033[3m parent daughter1 daughter2 ... \033[0m in options"); + + const EventType eventType = EventType( pEventType ); + + for(size_t i=0;i < datasets.size() ; i+=2 ){ + data.emplace_back( datasets[i], eventType ); + if( datasets[i+1] == "FLAT" ) mcs.emplace_back(Generator<>(eventType).generate(1e6)); + else mcs.emplace_back( datasets[i+1], eventType, GetGenPdf(true) ); + } + + std::vector fcs(data.size()); + std::vector> pdfs; + + pdfs.reserve(data.size()); + + SimFit totalLL; + MinuitParameterSet mps; + mps.loadFromStream(); + for(size_t i = 0; i < data.size(); ++i){ + fcs[i] = PolarisedSum(eventType, mps); + pdfs.emplace_back( make_pdf(fcs[i] ) ); + pdfs[i].setEvents(data[i]); + auto& mc = mcs[i]; + pdfs[i].forEach([&mc](auto& pdf){pdf.setMC(mc);}); + totalLL.add( pdfs[i] ); + } + Minimiser mini( totalLL, &mps ); + mini.doFit(); + FitResult(mini).writeToFile("Fitter.log"); + TFile* output_plots = TFile::Open( plotFile.c_str(), "RECREATE"); + for( size_t i = 0 ; i < data.size(); ++i ) + { + INFO("Making figures for sample: " << i << " ..."); + auto dataPlots = data[i].makeDefaultProjections( Prefix("Data_"+std::to_string(i))); + for( auto& p : dataPlots ) p->Write(); + size_t counter = 0; + for_each(pdfs[i].m_pdfs, [&]( auto& f ){ + auto mc_plots = mcs[i].makeDefaultProjections(WeightFunction(f), Prefix("Model_sample_"+std::to_string(i)+"_cat"+std::to_string(counter))); + for( auto& plot : mc_plots ) + { + plot->Scale( ( data[i].integral() * f.getWeight() ) / plot->Integral() ); + plot->Write(); + } + counter++; + } ); + } + output_plots->Close(); +} diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index 5ef8d561944..c70cc4a353b 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -109,7 +109,7 @@ std::complex CouplingConstant::operator()() const { return isCartesian ? std::accumulate( couplings.begin(), couplings.end(), complex_t(1,0), - [this](auto& prod, auto& coupling){ return prod * complex_t( coupling.first->mean(), coupling.second->mean() ) ; } ) + [](auto& prod, auto& coupling){ return prod * complex_t( coupling.first->mean(), coupling.second->mean() ) ; } ) : std::accumulate( couplings.begin(), couplings.end(), complex_t(1,0), [this](auto& prod, auto& coupling){ return prod * coupling.first->mean() * exp( 1i* this->sf * coupling.second->mean() ) ; } ); } diff --git a/src/EventList.cpp b/src/EventList.cpp index 3d1daa9c173..a35fbfd2fd6 100644 --- a/src/EventList.cpp +++ b/src/EventList.cpp @@ -246,9 +246,19 @@ double EventList::norm() return m_norm; } +void EventList::clear() +{ + m_data.clear(); +} -void EventList::clear() { m_data.clear(); } -void EventList::erase( const std::vector::iterator& begin, const std::vector::iterator& end ) +void EventList::erase(const std::vector::iterator& begin, + const std::vector::iterator& end) { m_data.erase( begin, end ); } + +void EventList::reserveCache(const size_t& size) +{ + if ( size >= at(0).cacheSize() ) + for (auto& evt : *this) evt.resizeCache(evt.cacheSize() + size); +} diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 1b91a87a9a2..99e0530ed63 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -126,6 +126,10 @@ void PolarisedSum::prepare() size_t nChanges = 0; ProfileClock tEval; size_t size_of = size() / m_matrixElements.size(); + + if( m_events != nullptr ) m_events->reserveCache( size() ); + if( m_integrator.isReady() ) m_integrator.events().reserveCache( size() ); + for( size_t i = 0; i < m_matrixElements.size(); ++i ){ ProfileClock tMEval; auto& t = m_matrixElements[i]; diff --git a/src/Wigner.cpp b/src/Wigner.cpp index 67cfdacb856..0588a4b44ef 100644 --- a/src/Wigner.cpp +++ b/src/Wigner.cpp @@ -168,8 +168,6 @@ std::vector AmpGen::calculate_recoupling_constants( f.factor = sqrt( (2.*L + 1. )/( 2.*J + 1. ) ); f.cg1 = CG(L ,0 ,S ,m1-m2,J,m1-m2); f.cg2 = CG(j1,m1,j2,-m2 ,S,m1-m2); - // f.cg1 = CG(L ,0 ,S ,m1-m2,J,M); - // f.cg2 = CG(j1,m1,j2,-m2 ,S,M); f.p = sqrt( (2*L + 1 )/(2*J+1) ); f.factor *= f.cg1 * f.cg2; if( f.factor != 0 ) rt.push_back(f); From 08dd370cb3a0042b352116e3436f344967af5808 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 21 Jun 2019 16:32:11 +0200 Subject: [PATCH 075/250] Minor fix in poly, add generic shapes in quasiparticles, improvements in README.md --- AmpGen/Lineshapes.h | 2 +- README.md | 175 +++++++++++++++++++------------------ options/D02Kpipipi.opt | 1 + options/D02piKpipi.opt | 5 +- options/mass_width.csv | 3 +- options/pdgID_to_latex.dat | 1 + src/Lineshapes.cpp | 6 +- src/Lineshapes/Poly.cpp | 7 +- src/Particle.cpp | 21 +++-- 9 files changed, 119 insertions(+), 102 deletions(-) diff --git a/AmpGen/Lineshapes.h b/AmpGen/Lineshapes.h index e4334613381..dbb2d554f81 100644 --- a/AmpGen/Lineshapes.h +++ b/AmpGen/Lineshapes.h @@ -390,7 +390,7 @@ namespace AmpGen Expression pol( const AmpGen::Expression& X, const std::vector& p ); - std::vector parameterVector( const std::string& name, const unsigned int& nParam ); + std::vector parameterVector(const std::string& name, const size_t& nParam); Expression width( const Expression& s, const Expression& s1, const Expression& s2, const Expression& mass, const Expression& width, const Expression& radius, unsigned int L, diff --git a/README.md b/README.md index 9c31407efbd..b6b6038a40b 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ AmpGen is a library and set of applications for fitting and generating multi-body particle decays using the isobar model. It developed out of the MINT project used in the fitting of three and four-body pseudoscalar decays by the CLEO-c and LHCb colloborations. The library can handle the fitting and generation of a wide variety of final states, including those involving fermions and photons, as well as polarised initial states. -Source code for the evaluation of amplitudes is dynamically generated by a custom engine, JIT compiled and dynamically linked to the user programme at runtime, which results in high flexibility and performance. +Source code for the evaluation of amplitudes is dynamically generated by a custom engine, JIT compiled and dynamically linked to the user programme at runtime, which results in high flexibility and performance. -## Table of Contents +## Table of Contents * [Getting Started](#getting-started) * [Applications](#applications) * [Examples](#examples) @@ -27,22 +27,22 @@ git clone http://github.com/GooFit/AmpGen/ --recursive There is at the time of writing only a master branch (FIXME) ##### Build requirements: -* cmake >= 3.11.0 -* C++ compiler with CXX standard >= 14 (gcc >= 4.9.3, clang ~ 5). +* cmake >= 3.11.0 +* C++ compiler with CXX standard >= 14 (gcc >= 4.9.3, clang ~ 5). Defaults to Cxx17 (enable cxx14 with cmake flag `-DCMAKE_CXX_STANDARD=14` ) * ROOT >= 6 with MathMore - To (re)configure root with these options, use the additional command line options `-Dcxx14 -Dmathmore=ON` when configuring the installation of ROOT. + To (re)configure root with these options, use the additional command line options `-Dcxx14 -Dmathmore=ON` when configuring the installation of ROOT. ##### Optional: -* boost >= 1.67.0 for unit tests -* xROOTd for network file access +* boost >= 1.67.0 for unit tests +* xROOTd for network file access * OpenMP for multithreading -* ROOT >= 6 with MathMore and Minuit2 enabled. The external version of Minuit2 provided as an external package of GooFit is used if the ROOT version is not unavailable. - To (re)configure root with these options, use the additional command line options `-Dcxx14 -Dminuit2=ON -Dmathmore=ON` when configuring the installation of ROOT. +* ROOT >= 6 with MathMore and Minuit2 enabled. The external version of Minuit2 provided as an external package of GooFit is used if the ROOT version is not unavailable. + To (re)configure root with these options, use the additional command line options `-Dcxx14 -Dminuit2=ON -Dmathmore=ON` when configuring the installation of ROOT. #### Building -The configuration of the AmpGen build is performed by cmake. -It is recommended to use a build directory to keep the source tree clean. +The configuration of the AmpGen build is performed by cmake. +It is recommended to use a build directory to keep the source tree clean. ```shell mkdir build @@ -50,12 +50,12 @@ cd build cmake .. make ``` -This will build the shared library, several standalone test applications, and a set of unit tests. +This will build the shared library, several standalone test applications, and a set of unit tests. #### Usage with ROOT -The library can be used interactively in conjunction with the ROOT C++ interpreter by adding the following lines -to the users root login script +The library can be used interactively in conjunction with the ROOT C++ interpreter by adding the following lines +to the users root login script ``` gSystem->Load("path_to_ampgen/build/lib/libAmpGen.so"); @@ -76,47 +76,47 @@ In order to build stand-alone on LXPLUS, you will need a valid development envir ```shell lb-run -c x86_64-centos7-gcc62-opt ROOT $SHELL ``` -Additionally, the ROOT versions installed on cvfms generally require C++17 support when building. +Additionally, the ROOT versions installed on cvfms generally require C++17 support when building. -Several examples of usages of the library are included in the apps directory and are -built alongside the library. -All standalone programs can accept both options files and command line arguments. -They also support `--help` to print help for key arguments to the program. -This will also run the program, as arguments can be defined throughout each of the programs rather than all defined at the beginning. +Several examples of usages of the library are included in the apps directory and are +built alongside the library. +All standalone programs can accept both options files and command line arguments. +They also support `--help` to print help for key arguments to the program. +This will also run the program, as arguments can be defined throughout each of the programs rather than all defined at the beginning. -### Options files and decay descriptors +### Options files and decay descriptors Options files will generally contain the description of one or more particle decays, -as well as other settings such as input/output locations, global flags such as -whether complex numbers should be interpreted as cartesian or polar, and other parameters +as well as other settings such as input/output locations, global flags such as +whether complex numbers should be interpreted as cartesian or polar, and other parameters such as the masses and widths of particles is these differ from those given in the PDG. - -A minimal example options file for the generator application could contain: + +A minimal example options file for the generator application could contain: ``` EventType D0 K+ pi- pi- pi+ -# Real / Amplitude | Imaginary / Phase +# Real / Amplitude | Imaginary / Phase # Fix? Value Step | Fix? Value Step D0{K*(892)0{K+,pi-},rho(770)0{pi+,pi-}} 2 1 0 2 0 0 ``` -The EventType specifies the initial and final states requested by the user. -This gives the ordering of particles used in input data, in output code, and used in internal computations. +The EventType specifies the initial and final states requested by the user. +This gives the ordering of particles used in input data, in output code, and used in internal computations. This also defines how the amplitude source code must be interfaced with external packages, i.e. MC generators such as EvtGen. The decay products of a particle are enclosed within curly braces, for example ``` K*(892)0{K+,pi-} ``` -describes an excited vector kaon decaying into a charged kaon and pion. -For more details about the API for describing particle decays, see [AmpGen::Particle](https://goofit.github.io/AmpGen/de/dd7/class_amp_gen_1_1_particle.html) -The other numbers on the lines that describe the decays parameterise the coupling to this channel, +describes an excited vector kaon decaying into a charged kaon and pion. +For more details about the API for describing particle decays, see [AmpGen::Particle](https://goofit.github.io/AmpGen/de/dd7/class_amp_gen_1_1_particle.html) +The other numbers on the lines that describe the decays parameterise the coupling to this channel, either in terms of real and imaginary parts or an amplitude and a phase. -Each parameter is specified in terms of three numbers: the _fix_ flag, the initial value, and the step size. -The possible options for the _fix_ flag are: +Each parameter is specified in terms of three numbers: the _fix_ flag, the initial value, and the step size. +The possible options for the _fix_ flag are: * Free (fix=0) and a step size of not 0. * Fixed (fix=2, for historical reasons) -* Compile-Time-Constant (fix=3) which indicates that the parameter should be treated as a (JIT) compile time constant, which in some cases allows for more aggressive optimisations to be performed. +* Compile-Time-Constant (fix=3) which indicates that the parameter should be treated as a (JIT) compile time constant, which in some cases allows for more aggressive optimisations to be performed. -These options can be used in the Generator application, which is described below. +These options can be used in the Generator application, which is described below. Decays can either be specified fully inline, as above, or split into multiple steps, which is useful for treating the so called _cascade_ decays, an example of which is shown below. ``` @@ -125,20 +125,20 @@ D0{K(1)(1270)+,pi-} 0 1 0.1 0 0 K(1)(1270)+{rho(770)0{pi+,pi-},K+} 2 1 0 2 0 0 K(1)(1270)+{K*(892)0{K+,pi-},pi+} 0 1 0.1 0 0 0.1 ``` -The production/decay couplings of the K(1270) resonance are now defined in terms of the coupling to the rho(770),K+ channel, -which can be useful in making comparisons between different production modes of a resonance. -Additional care must be taken in such a case to not introduce redundant degrees of freedom. +The production/decay couplings of the $K_1(1270)^+$ resonance are now defined in terms of the coupling to the $\rho(770)^0 K^+$ channel, +which can be useful in making comparisons between different production modes of a resonance. +Additional care must be taken in such a case to not introduce redundant degrees of freedom. -Configuration can be split over multiple files by the using _Import_ keyword, for example, to import the parameters for the isoscalar K-matrix, the line +Configuration can be split over multiple files by the using _Import_ keyword, for example, to import the parameters for the isoscalar K-matrix, the line ``` Import $AMPGENROOT/options/kMatrix.opt ``` -can be added to options file. Multiple user configuration files can also be specified by including multiple files on the command line. +can be added to options file. Multiple user configuration files can also be specified by including multiple files on the command line. ## Applications -This section details the prebuilt command line applications that use the AmpGen library for some common functionality, such as generating Toy Monte Carlo samples -and debugging amplitudes. +This section details the prebuilt command line applications that use the AmpGen library for some common functionality, such as generating Toy Monte Carlo samples +and debugging amplitudes. ### Table of contents * [Generator](#generator) @@ -153,28 +153,33 @@ The standalone generator for models can be used as Generator MyOpts.opt --nEvents=10000 --Output=output.root ``` -Which generates 10000 events of the model described in MyOpts.opt and saves them to output.root. +Which generates 10000 events of the model described in MyOpts.opt and saves them to output.root. The output should include a tree (DalitzEventList) of candidates with the full four-vectors, as well as one- and two-dimensional projections, an example of which is shown below: ![s01](doc/figs/s01.png) -In particular, the tree indicates the way in which data is by default loaded into the _Event_ / _EventList_ class. +In particular, the tree indicates the way in which data is by default loaded into the _Event_ / _EventList_ class. +Several models for different $D^{0}$ decays published by the LHCb collaboration are included in the options directory. These options do not include EventTypes so as they can be included as part of a larger decay chain if required. For example, to generate $10^6$ toy $D^{0}\to K^{-} \pi^+ \pi^+ \pi^- $ events: +``` +./Generator options/D02Kpipipi.opt --EventType "D0 K- pi+ pi+ pi-" --nEvents 1000000 +``` + -### Debugger +### Debugger -The debugger application is a tool for producing verbose information debugging for amplitudes and models. It is used on an options file as +The debugger application is a tool for producing verbose information debugging for amplitudes and models. It is used on an options file as ``` ./Debugger MyOpts.opt ``` -which calculates each amplitude at a randomly generated point in phase space, as well as calculating the total amplitude accounting for complex -couplings. Also computed is the amplitude for the P conjugate event. A more useful application is the _verbose_ debugging mode which can be -activated by +which calculates each amplitude at a randomly generated point in phase space, as well as calculating the total amplitude accounting for complex +couplings. Also computed is the amplitude for the P conjugate event. A more useful application is the _verbose_ debugging mode which can be +activated by ``` ./Debugger MyOpts.opt --CoherentSum::Debug ``` -which produces a large number of intermediate steps in the calculation of each amplitude, which are added to the calculation using the -ADD_DEBUG and ADD_DEBUG_TENSOR macros in the code generation. For example, in src/Lineshapes/BW.cpp. -(n.b), if the model is a PolarisedSum, i.e. handles spin in the initial/final state, the flag PolarisedSum::Debug should be used instead of CoherentSum::Debug, in order +which produces a large number of intermediate steps in the calculation of each amplitude, which are added to the calculation using the +ADD_DEBUG and ADD_DEBUG_TENSOR macros in the code generation. For example, in src/Lineshapes/BW.cpp. +(n.b), if the model is a PolarisedSum, i.e. handles spin in the initial/final state, the flag PolarisedSum::Debug should be used instead of CoherentSum::Debug, in order to generate all of the intermediate calculations of the amplitude. ### ConvertToSourceCode @@ -192,11 +197,11 @@ g++ -Ofast -shared -rdynamic --std=c++14 -fPIC MyFile.cpp -o MyFile.so ### SignalOnlyFitter -An example fitter is provided in _examples/SignalOnlyFitter.cpp_, which as the name suggests only has a single signal component in the fit. -The free parameters of the fit are specified in the same way as the Generator, -with the additional relevant slots being _DataSample_ which specifies the signal sample to fit, -which is presumed to already have the selection applied, and _Branches_ which takes a list of branch names, -and defaults to the format used by the Generator etc. More details can be found with +An example fitter is provided in _examples/SignalOnlyFitter.cpp_, which as the name suggests only has a single signal component in the fit. +The free parameters of the fit are specified in the same way as the Generator, +with the additional relevant slots being _DataSample_ which specifies the signal sample to fit, +which is presumed to already have the selection applied, and _Branches_ which takes a list of branch names, +and defaults to the format used by the Generator etc. More details can be found with ``` SignalOnlyFitter --help ``` @@ -206,23 +211,23 @@ Generator MyOpts.opt --nEvents 100000 SignalOnlyFitter MyOpts.opt --DataSample Generate_Output.root ``` -## Advanced +## Advanced -This section contains miscellaneous details on more advanced functionality, including using python bindings and alternative parameterisation of the spin factors. +This section contains miscellaneous details on more advanced functionality, including using python bindings and alternative parameterisation of the spin factors. ### Table of contents * [Python Bindings](#python-bindings) * [Particle Properties and Lineshape parameters](#particle-properties-and-lineshape-parameters) * [Fit parameters and expressions](#fit-parameters-and-expressions) * [Spin Formalisms](#spin-formalisms) - +* [Quasi-Particles](#quasi-particles) ### Python Bindings Models built into a shared library can be used in python using the following flags into ConvertToSourceCode: -```shell +```shell ./ConvertToSourceCode MyOpts.opt --Output=MyFile.cpp --OutputEvents=events.csv --IncludePythonBindings ``` -where normalisation events are also output for testing purposes in events.csv. +where normalisation events are also output for testing purposes in events.csv. This can then be used with the python bindings in ampgen.py: ```python from ampgen import FixedLib @@ -241,48 +246,48 @@ fcn2 = data.apply(model.FCN, axis=1) The particles available and their default properties can be found in *options/mass\_width.csv* using the MC format of the 2008 PDG. Additional pseudoparticles, such as nonresonant states and terms for use in conjunction with K-matrices are defined by *options/MintDalitzSpecialParticles.csv*. Any additional user defined particles should be added here. -For the default lineshape (the relavistic Breit-Wigner or BW), there are three parameters: The mass, the width and the Blatt-Weisskopf radius. -These default to their PDG values, but can be overridden in the options file with parameters: *particleName*\_mass, *particleName*\_width, *particleName*\_radius. -So if the K(1270)+ mass was allowed to vary, the line: +For the default lineshape (the relavistic Breit-Wigner or BW), there are three parameters: The mass, the width and the Blatt-Weisskopf radius. +These default to their PDG values, but can be overridden in the options file with parameters: *particleName*\_mass, *particleName*\_width, *particleName*\_radius. +So if the K(1270)+ mass was allowed to vary, the line: ``` K(1270)+_mass 0 1.270 0.01 ``` -could be added to the user configuration. +could be added to the user configuration. Other lineshapes may define other parameters, for example channel couplings or pole masses in the case of the K-matrices, which can be set or varied in a similar manner. ### Fit parameters and expressions -Parameters can either be specified by three parameters, in the case of a scalar parameter such as a mass or a width, or with six parameters in the case of a complex parameter such as a coupling. -Upper and lower bounds on parameters can also be set by specifying a parameter with five parameters or ten parameters for a scalar or complex, respectively. -For example, if we wished to vary the K(1)(1270)+ mass in the above example, but restricting the allowed values in the range \[0.0,2.0\] GeV: +Parameters can either be specified by three parameters, in the case of a scalar parameter such as a mass or a width, or with six parameters in the case of a complex parameter such as a coupling. +Upper and lower bounds on parameters can also be set by specifying a parameter with five parameters or ten parameters for a scalar or complex, respectively. +For example, if we wished to vary the mass of the $K_1(1270)^+$ meson in the above example, but restricting the allowed values in the range $[0.0,2.0]\,\mathrm{GeV}$: ``` K(1)(1270)+_mass 0 1.27 0.01 0.0 2.0 ``` -(Scalar) parameters can also be related to each other via expressions. -Suppose for example we have K(1)(1270)+ and K(1)(1270)bar- in the same fit (for example, for D-\>KKpipi) -The properties of one can be allowed to vary, for example the K(1)(1270)+, and the other fixed to the same value, using: +Parameters can also be related to each other via expressions, +Suppose for example we have $K_1(1270)^+$ and $K_1(1270)^-$ in the same fit (for example, for $D^0 \to K^- K^+ \pi^- \pi^+$) +The properties of one can be allowed to vary, for example the $K_1(1270)^+$, and the other fixed to the same value, using: ``` -K(1)(1270)+_mass 0 1.27 0.01 0.0 2.0 -K(1)(1270)bar-_mass = K(1)(1270)+_mass +K(1)(1270)+_mass 0 1.27 0.01 0.0 2.0 +K(1)(1270)bar-_mass = K(1)(1270)+_mass ``` -Parameter expressions are whitespace delimited due to the abundance of **odd** glyphs such as brackets and +/- in the names of parameters. -Expressions support the binary operations (+,-,/,*,^), as well as common unary functions such as sqrt, trigonometric functions etc. +Parameter expressions are whitespace delimited due to the abundance of **odd** glyphs such as brackets and +/- in the names of parameters. +Expressions support the binary operations $(+,-,/,* )$, as well as common unary functions such as sqrt, trigonometric functions etc. ### Spin Formalisms -AmpGen implements both the covariant tensor (or Rarita-Schwinger) and canonical helicity formalism for describing the angular momentum component of decays. -Both formalisms refer to states of well-defined orbital angular momentum, as opposed to the helicity states, as the states with well-defined orbital angular momentum have a straightforward parity and momentum dependences. -The default formalism is the covariant tensor formalism, but this can be switched to the canonical formalism changing the flag +AmpGen implements both the covariant tensor (or Rarita-Schwinger) and canonical helicity formalism for describing the angular momentum component of decays. +Both formalisms refer to states of well-defined orbital angular momentum, as opposed to the helicity states, as the states with well-defined orbital angular momentum have a straightforward parity and momentum dependences. +The default formalism is the covariant tensor formalism, but this can be switched to the canonical formalism changing the flag ``` Particle::SpinFormalism Canonical ## default = Covariant ``` -in the options file. -The spin formalism for an individual decay chain can be specified by changing the attribute SpinFormalism in the decay descriptor. For example, +in the options file. +The spin formalism for an individual decay chain can be specified by changing the attribute SpinFormalism in the decay descriptor. For example, ``` D0[SpinFormalism=Canonical]{K*(892)bar0,rho(770)0} ``` -selects the S-wave of the K*, rho system. The user can also specify systems of helicity couplings in the canonical formalism, using the attribute _helAmp_. +selects the S-wave of the $K^* \rho$ system. The user can also specify systems of helicity couplings in the canonical formalism, using the attribute _helAmp_. For example, suppose the transversity amplitudes were used rather than the canonical, then the user can specify ``` D0[SpinFormalism=Canonical;helAmp=Long]{K*(892)bar0,rho(770)0} @@ -307,14 +312,15 @@ t2 { ``` That is specified as sets of three numbers, firstly the coupling, and then the two particle helicities. So in this example, the longitudinal amplitude is the 00 helicity state, while the two transverse amplitudes and the sum and difference of the two other helicity amplitudes. +### Quasi-Particles ## Acknowledgements The development of this software has been supported by the National Science Foundation under grant PHY-1414736 and through a subcontract under Cooperative Agreement OAC-1836650. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the developers and do not necessarily reflect the views of the National Science Foundation.

- - + +

@@ -322,4 +328,3 @@ The development of this software has been supported by the National Science Fou [travis-badge]: https://travis-ci.org/GooFit/AmpGen.svg?branch=master [license-badge]: https://img.shields.io/badge/License-GPL%20v2-blue.svg [travis-link]: https://travis-ci.org/GooFit/AmpGen - diff --git a/options/D02Kpipipi.opt b/options/D02Kpipipi.opt index 5fe22c2017d..b4c83e6ab98 100644 --- a/options/D02Kpipipi.opt +++ b/options/D02Kpipipi.opt @@ -1,4 +1,5 @@ # Description of CF amplitude D0 -> K-,pi+,pi+,pi- +EventType D0 K- pi+ pi+ pi- Import $AMPGENROOT/options/kMatrix.opt a(1)(1260)-::Spline 40 0.18412 1.9 diff --git a/options/D02piKpipi.opt b/options/D02piKpipi.opt index 2ef30fe904d..189951d7289 100644 --- a/options/D02piKpipi.opt +++ b/options/D02piKpipi.opt @@ -1,8 +1,11 @@ # Description of DCS amplitude D0 -> K+,pi-,pi-,pi+ - Import $AMPGENROOT/options/Dbar02piKpipi.opt #necessary for K1 couplings / shape parameters +CouplingConstant::Coordinates polar +CouplingConstant::AngularUnits deg +CoherentSum::Verbosity 0 + D0_radius 2 3.7559 0 D0{K*(892)0{K+,pi-},rho(770)0{pi+,pi-}} 2 0.205 0.019 2 -8.5 4.7 D0[P]{K*(892)0{K+,pi-},rho(770)0{pi+,pi-}} 2 0.390 0.002 2 -91.4 0.4 diff --git a/options/mass_width.csv b/options/mass_width.csv index 4c90987eb09..34736146064 100644 --- a/options/mass_width.csv +++ b/options/mass_width.csv @@ -721,6 +721,7 @@ 3.1229E+03 ,1.3E+00,1.3E+00,4.0E+00 ,4.0E+00,4.0E+00,? , ,? ,?, ,F, , +,1,S,Xi(c)(3123) ,usc 2.6975E+03 ,2.6E+00,2.6E+00,9.6E-09 ,1.7E-09,1.7E-09,0 , ,1/2 ,+, ,F, 4332, 0,3,R,Omega(c) ,ssc 2.7683E+03 ,3.0E+00,3.0E+00,-1 ,-1 ,-1 ,0 , ,3/2 ,+, ,F, 4334, 0,3,R,Omega(c)(2770) ,ssc +3.0004E+03 ,0.2E+00,0.2E+00,4.5E+00 ,0.7E+00,0.7E+00,0 , ,1/2 ,+, ,F, , 0,3,R,Omega(c)(3000) ,ssc 3.5189E+03 ,9.0E-01,9.0E-01,2.0079E-08 ,-1 ,-1 ,? , ,? ,?, ,F, 4422, ++,1,S,Xi(cc) ,ucc 3.5189E+03 ,9.0E-01,9.0E-01,2.0079E-08 ,-1 ,-1 ,? , ,? ,?, ,F, 4412, +,1,S,Xi(cc) ,dcc 5.6202E+03 ,1.6E+00,1.6E+00,4.79E-10 ,1.7E-11,1.7E-11,0 , ,1/2 ,+, ,F, 5122, 0,3,R,Lambda(b) ,udb @@ -732,4 +733,4 @@ 5.8364E+03 ,2.8E+00,2.8E+00,-1 ,-1 ,-1 ,1 , ,3/2 ,+, ,F, 5114, -,3,R,Sigma(b)* ,ddb 5.7924E+03 ,3.0E+00,3.0E+00,1.42E-12 ,2.8E-13,2.4E-13,1/2, ,1/2 ,+, ,F, 5232, -,3,R,Xi(b) ,dsb 5.7924E+03 ,3.0E+00,3.0E+00,4.7E-10 ,9.0E-11,8.0E-11,1/2, ,1/2 ,+, ,F, 5132, 0,3,R,Xi(b) ,usb - +6.0461E+03 ,1.7E+00,1.7E+00,4.7E-10 ,9.0E-11,8.0E-11,1/2, ,1/2 ,+, ,F, 5334, -,3,R,Omega(b) ,ssb diff --git a/options/pdgID_to_latex.dat b/options/pdgID_to_latex.dat index 6c72b3250ee..86724739cc1 100644 --- a/options/pdgID_to_latex.dat +++ b/options/pdgID_to_latex.dat @@ -296,6 +296,7 @@ 3334 \Omega^{-} \Omega^{+} 4332 \Omega_{c}^{0} \Omega_{c}^{0} 4334 \Omega_{c}^{*0} \Omega_{c}^{*0} +5334 \Omega_{b}^{-} \Omega_{b}^{+} 9981 0^{+} 0^{+} 9983 1^{+} 1^{+} 9985 2^{+} 2^{+} diff --git a/src/Lineshapes.cpp b/src/Lineshapes.cpp index c61060562a7..e77940c4451 100644 --- a/src/Lineshapes.cpp +++ b/src/Lineshapes.cpp @@ -63,11 +63,11 @@ Expression AmpGen::BL( const Expression& s, return sqrt( BlattWeisskopf( q2 * radius * radius, L ) / BlattWeisskopf( q20 * radius * radius, L ) ); } -std::vector AmpGen::parameterVector( const std::string& name, const unsigned int& nParam ) +std::vector AmpGen::parameterVector( const std::string& name, const size_t& nParam ) { std::vector returnVector; - for ( unsigned int i = 0; i < nParam; ++i ) - returnVector.push_back( Parameter( name + std::to_string( i ) ) ); + for (size_t i = 0; i != nParam; ++i ) + returnVector.emplace_back(Parameter(name + std::to_string(i))); return returnVector; } diff --git a/src/Lineshapes/Poly.cpp b/src/Lineshapes/Poly.cpp index 87ae781931a..5f21b6a63da 100644 --- a/src/Lineshapes/Poly.cpp +++ b/src/Lineshapes/Poly.cpp @@ -9,7 +9,10 @@ using namespace AmpGen; DEFINE_LINESHAPE( Poly ) { - unsigned int degree = NamedParameter( lineshapeModifier + "::Degree" ); - auto params = parameterVector( lineshapeModifier + "_c", degree ); + size_t degree = NamedParameter( lineshapeModifier + "::Degree" ); + auto params = parameterVector(lineshapeModifier + "_c", degree + 1); + ADD_DEBUG(s, dbexpressions); + if( dbexpressions != nullptr ) for( size_t i=0;iemplace_back( lineshapeModifier +"_c"+std::to_string(i), params[i] ); return pol(s, params); } diff --git a/src/Particle.cpp b/src/Particle.cpp index cecc12373ce..30eb7a0a5f6 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -318,15 +318,18 @@ Expression Particle::propagator( DebugSymbols* db ) const Expression total( 1. ); DEBUG( "Getting lineshape " << m_lineshape << " for " << m_name ); Expression s = massSq(); - if ( m_daughters.size() == 2 ) { - auto prop = Lineshape::Factory::get(m_lineshape, s, daughter(0)->massSq(), daughter(1)->massSq(), m_name, m_orbital, db); - total = total * make_cse(prop); - } - else if ( m_daughters.size() == 3 ) { - std::string shape = m_lineshape == "BW" ? "SBW" : m_lineshape; - auto prop = Lineshape::Factory::get(shape, massSq(), {daughter(0)->P(), daughter(1)->P(), daughter(2)->P()}, m_name, m_orbital, db ); - total = total * make_cse(prop); - } + Expression prop = 1; + if ( m_daughters.size() == 2 ) + prop = Lineshape::Factory::get(m_lineshape, s, daughter(0)->massSq(), daughter(1)->massSq(), m_name, m_orbital, db); + else if ( m_daughters.size() == 3 ) + prop = Lineshape::Factory::get(m_lineshape == "BW" ? "SBW" : m_lineshape, massSq(), {daughter(0)->P(), daughter(1)->P(), daughter(2)->P()}, m_name, m_orbital, db ); + else if ( m_daughters.size() == 1 && m_lineshape != "BW" && m_lineshape != "FormFactor" ) + { + std::vector p_vector; + for( auto& d : m_daughters[0]->daughters() ) p_vector.emplace_back( d->P() ); + prop = Lineshape::Factory::get(m_lineshape, massSq(), p_vector, m_name, m_orbital, db ); + } + total = total * make_cse(prop); for(auto& d : m_daughters) total = total*make_cse(d->propagator(db)); if(db != nullptr) db->emplace_back("A("+uniqueString()+")", total); return total; From 6caa622022426760cfaa0d6e6111749c9d8373ea Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 21 Jun 2019 22:28:00 +0200 Subject: [PATCH 076/250] Add prerendered formulae to the Markdown, minor fixes to Particle --- AmpGen/Utilities.h | 2 +- README.md | 33 ++--- README.tex.md | 326 +++++++++++++++++++++++++++++++++++++++++ doc/figs/tex/fig0.png | Bin 0 -> 688 bytes doc/figs/tex/fig1.png | Bin 0 -> 744 bytes doc/figs/tex/fig10.png | Bin 0 -> 716 bytes doc/figs/tex/fig11.png | Bin 0 -> 688 bytes doc/figs/tex/fig12.png | Bin 0 -> 565 bytes doc/figs/tex/fig13.png | Bin 0 -> 450 bytes doc/figs/tex/fig14.png | Bin 0 -> 342 bytes doc/figs/tex/fig2.png | Bin 0 -> 404 bytes doc/figs/tex/fig3.png | Bin 0 -> 406 bytes doc/figs/tex/fig4.png | Bin 0 -> 708 bytes doc/figs/tex/fig5.png | Bin 0 -> 688 bytes doc/figs/tex/fig6.png | Bin 0 -> 688 bytes doc/figs/tex/fig7.png | Bin 0 -> 761 bytes doc/figs/tex/fig8.png | Bin 0 -> 688 bytes doc/figs/tex/fig9.png | Bin 0 -> 675 bytes src/OptionsParser.cpp | 6 +- src/Particle.cpp | 3 +- 20 files changed, 347 insertions(+), 23 deletions(-) create mode 100644 README.tex.md create mode 100644 doc/figs/tex/fig0.png create mode 100644 doc/figs/tex/fig1.png create mode 100644 doc/figs/tex/fig10.png create mode 100644 doc/figs/tex/fig11.png create mode 100644 doc/figs/tex/fig12.png create mode 100644 doc/figs/tex/fig13.png create mode 100644 doc/figs/tex/fig14.png create mode 100644 doc/figs/tex/fig2.png create mode 100644 doc/figs/tex/fig3.png create mode 100644 doc/figs/tex/fig4.png create mode 100644 doc/figs/tex/fig5.png create mode 100644 doc/figs/tex/fig6.png create mode 100644 doc/figs/tex/fig7.png create mode 100644 doc/figs/tex/fig8.png create mode 100644 doc/figs/tex/fig9.png diff --git a/AmpGen/Utilities.h b/AmpGen/Utilities.h index afb78bdcf65..220698cf6b5 100644 --- a/AmpGen/Utilities.h +++ b/AmpGen/Utilities.h @@ -195,7 +195,7 @@ namespace AmpGen { bool isDir( const std::string& fname ); bool fileExists( const std::string& name ); - std::vector getListOfFiles( const std::string& directory, std::string patternString = "" ); + std::vector getListOfFiles(const std::string& directory, std::string patternString = ""); void printSplash(); void printReleaseNotes(const std::string& fname); diff --git a/README.md b/README.md index b6b6038a40b..caa1702d826 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ D0{K(1)(1270)+,pi-} 0 1 0.1 0 0 K(1)(1270)+{rho(770)0{pi+,pi-},K+} 2 1 0 2 0 0 K(1)(1270)+{K*(892)0{K+,pi-},pi+} 0 1 0.1 0 0 0.1 ``` -The production/decay couplings of the $K_1(1270)^+$ resonance are now defined in terms of the coupling to the $\rho(770)^0 K^+$ channel, +The production/decay couplings of the resonance are now defined in terms of the coupling to the channel, which can be useful in making comparisons between different production modes of a resonance. Additional care must be taken in such a case to not introduce redundant degrees of freedom. @@ -159,12 +159,12 @@ The output should include a tree (DalitzEventList) of candidates with the full f ![s01](doc/figs/s01.png) In particular, the tree indicates the way in which data is by default loaded into the _Event_ / _EventList_ class. -Several models for different $D^{0}$ decays published by the LHCb collaboration are included in the options directory. These options do not include EventTypes so as they can be included as part of a larger decay chain if required. For example, to generate $10^6$ toy $D^{0}\to K^{-} \pi^+ \pi^+ \pi^- $ events: +Several models for different decays published by the LHCb collaboration are included in the options directory. These options do not include EventTypes so as they can be included as part of a larger decay chain if required. For example, to generate toy events: + ``` ./Generator options/D02Kpipipi.opt --EventType "D0 K- pi+ pi+ pi-" --nEvents 1000000 ``` - ### Debugger The debugger application is a tool for producing verbose information debugging for amplitudes and models. It is used on an options file as @@ -243,36 +243,31 @@ fcn2 = data.apply(model.FCN, axis=1) ``` ### Particle Properties and Lineshape parameters -The particles available and their default properties can be found in *options/mass\_width.csv* using the MC format of the 2008 PDG. -Additional pseudoparticles, such as nonresonant states and terms for use in conjunction with K-matrices are defined by *options/MintDalitzSpecialParticles.csv*. -Any additional user defined particles should be added here. -For the default lineshape (the relavistic Breit-Wigner or BW), there are three parameters: The mass, the width and the Blatt-Weisskopf radius. -These default to their PDG values, but can be overridden in the options file with parameters: *particleName*\_mass, *particleName*\_width, *particleName*\_radius. -So if the K(1270)+ mass was allowed to vary, the line: +The particles available and their default properties can be found in *options/mass\_width.csv* using the MC format of the 2008 PDG. Additional pseudoparticles, such as nonresonant states and terms for use in conjunction with K-matrices are defined by *options/MintDalitzSpecialParticles.csv*. Any additional user defined particles should be added here. For the default lineshape (the relavistic Breit-Wigner or BW), there are three parameters: The mass, the width and the Blatt-Weisskopf radius. These default to their PDG values, but can be overridden in the options file with parameters: *particleName*\_mass, *particleName*\_width, *particleName*\_radius. To vary the mass of the meson, the line: ``` -K(1270)+_mass 0 1.270 0.01 +K(1)(1270)+_mass 0 1.270 0.01 ``` could be added to the user configuration. -Other lineshapes may define other parameters, for example channel couplings or pole masses in the case of the K-matrices, which can be set or varied in a similar manner. +Other lineshapes may define other parameters, for example channel couplings or pole masses in the case of the K-matrices, can be set or varied in a similar manner. ### Fit parameters and expressions Parameters can either be specified by three parameters, in the case of a scalar parameter such as a mass or a width, or with six parameters in the case of a complex parameter such as a coupling. Upper and lower bounds on parameters can also be set by specifying a parameter with five parameters or ten parameters for a scalar or complex, respectively. -For example, if we wished to vary the mass of the $K_1(1270)^+$ meson in the above example, but restricting the allowed values in the range $[0.0,2.0]\,\mathrm{GeV}$: +For example, if we wished to vary the mass of the meson in the above example, but restricting the allowed values in the range : ``` K(1)(1270)+_mass 0 1.27 0.01 0.0 2.0 ``` Parameters can also be related to each other via expressions, -Suppose for example we have $K_1(1270)^+$ and $K_1(1270)^-$ in the same fit (for example, for $D^0 \to K^- K^+ \pi^- \pi^+$) -The properties of one can be allowed to vary, for example the $K_1(1270)^+$, and the other fixed to the same value, using: +Suppose for example we have and in the same fit (for example, for ) +The properties of one can be allowed to vary, for example the , and the other fixed to the same value, using: ``` K(1)(1270)+_mass 0 1.27 0.01 0.0 2.0 K(1)(1270)bar-_mass = K(1)(1270)+_mass ``` Parameter expressions are whitespace delimited due to the abundance of **odd** glyphs such as brackets and +/- in the names of parameters. -Expressions support the binary operations $(+,-,/,* )$, as well as common unary functions such as sqrt, trigonometric functions etc. +Expressions support the binary operations , as well as common unary functions such as sqrt, trigonometric functions etc. ### Spin Formalisms @@ -287,8 +282,7 @@ The spin formalism for an individual decay chain can be specified by changing th ``` D0[SpinFormalism=Canonical]{K*(892)bar0,rho(770)0} ``` -selects the S-wave of the $K^* \rho$ system. The user can also specify systems of helicity couplings in the canonical formalism, using the attribute _helAmp_. -For example, suppose the transversity amplitudes were used rather than the canonical, then the user can specify +selects the S-wave of the system. The user can also specify systems of helicity couplings in the canonical formalism, using the attribute _helAmp_. For example, suppose the transversity amplitudes were used rather than the canonical, then the user can specify ``` D0[SpinFormalism=Canonical;helAmp=Long]{K*(892)bar0,rho(770)0} D0[SpinFormalism=Canonical;helAmp=t1]{K*(892)bar0,rho(770)0} @@ -310,10 +304,12 @@ t2 { -0.707106781 -1 -1 } ``` -That is specified as sets of three numbers, firstly the coupling, and then the two particle helicities. So in this example, the longitudinal amplitude is the 00 helicity state, while the two transverse amplitudes and the sum and difference of the two other helicity amplitudes. +That is specified as sets of three numbers, firstly the coupling, and then the two particle helicities. So in this example, the longitudinal amplitude is the helicity state, while the two transverse amplitudes and the sum and difference of the two other helicity amplitudes. ### Quasi-Particles + + ## Acknowledgements The development of this software has been supported by the National Science Foundation under grant PHY-1414736 and through a subcontract under Cooperative Agreement OAC-1836650. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the developers and do not necessarily reflect the views of the National Science Foundation. @@ -328,3 +324,4 @@ The development of this software has been supported by the National Science Fou [travis-badge]: https://travis-ci.org/GooFit/AmpGen.svg?branch=master [license-badge]: https://img.shields.io/badge/License-GPL%20v2-blue.svg [travis-link]: https://travis-ci.org/GooFit/AmpGen + diff --git a/README.tex.md b/README.tex.md new file mode 100644 index 00000000000..2cbb754f4f1 --- /dev/null +++ b/README.tex.md @@ -0,0 +1,326 @@ +[![Build Status][travis-badge]][travis-link] +[![License: LGPL v3][license-badge]](./LICENSE) + +

+ +

+AmpGen is a library and set of applications for fitting and generating multi-body particle decays using the isobar model. +It developed out of the MINT project used in the fitting of three and four-body pseudoscalar decays by the CLEO-c and LHCb colloborations. The library can handle the fitting and generation of a wide variety of final states, including those involving fermions and photons, as well as polarised initial states. + +Source code for the evaluation of amplitudes is dynamically generated by a custom engine, JIT compiled and dynamically linked to the user programme at runtime, which results in high flexibility and performance. + +## Table of Contents +* [Getting Started](#getting-started) +* [Applications](#applications) +* [Examples](#examples) +* [Advanced](#advanced) +* [API documentation](https://goofit.github.io/AmpGen/) +* [Acknowledgements](#acknowledgements) + +## Getting started +### Installation +#### Getting the source +Clone with git +``` +git clone http://github.com/GooFit/AmpGen/ --recursive +``` +There is at the time of writing only a master branch (FIXME) + +##### Build requirements: +* cmake >= 3.11.0 +* C++ compiler with CXX standard >= 14 (gcc >= 4.9.3, clang ~ 5). + Defaults to Cxx17 (enable cxx14 with cmake flag `-DCMAKE_CXX_STANDARD=14` ) +* ROOT >= 6 with MathMore + To (re)configure root with these options, use the additional command line options `-Dcxx14 -Dmathmore=ON` when configuring the installation of ROOT. + +##### Optional: +* boost >= 1.67.0 for unit tests +* xROOTd for network file access +* OpenMP for multithreading +* ROOT >= 6 with MathMore and Minuit2 enabled. The external version of Minuit2 provided as an external package of GooFit is used if the ROOT version is not unavailable. + To (re)configure root with these options, use the additional command line options `-Dcxx14 -Dminuit2=ON -Dmathmore=ON` when configuring the installation of ROOT. + +#### Building +The configuration of the AmpGen build is performed by cmake. +It is recommended to use a build directory to keep the source tree clean. + +```shell +mkdir build +cd build +cmake .. +make +``` +This will build the shared library, several standalone test applications, and a set of unit tests. + +#### Usage with ROOT + +The library can be used interactively in conjunction with the ROOT C++ interpreter by adding the following lines +to the users root login script + +``` + gSystem->Load("path_to_ampgen/build/lib/libAmpGen.so"); + gROOT->ProcessLine(".include path_to_ampgen"); +``` +##### LLVM +You can also build AmpGen with LLVM. The only change you might want when using Apple LLVM +is to specifically specify the location of the build tool for AmpGen's JIT: + +```shell +-DAMPGEN_CXX=$(which c++) +``` + +##### LXPLUS + +In order to build stand-alone on LXPLUS, you will need a valid development environment; the following line will work: + +```shell +lb-run -c x86_64-centos7-gcc62-opt ROOT $SHELL +``` +Additionally, the ROOT versions installed on cvfms generally require C++17 support when building. + +Several examples of usages of the library are included in the apps directory and are +built alongside the library. +All standalone programs can accept both options files and command line arguments. +They also support `--help` to print help for key arguments to the program. +This will also run the program, as arguments can be defined throughout each of the programs rather than all defined at the beginning. + +### Options files and decay descriptors + +Options files will generally contain the description of one or more particle decays, +as well as other settings such as input/output locations, global flags such as +whether complex numbers should be interpreted as cartesian or polar, and other parameters +such as the masses and widths of particles is these differ from those given in the PDG. + +A minimal example options file for the generator application could contain: +``` +EventType D0 K+ pi- pi- pi+ +# Real / Amplitude | Imaginary / Phase +# Fix? Value Step | Fix? Value Step +D0{K*(892)0{K+,pi-},rho(770)0{pi+,pi-}} 2 1 0 2 0 0 +``` +The EventType specifies the initial and final states requested by the user. +This gives the ordering of particles used in input data, in output code, and used in internal computations. +This also defines how the amplitude source code must be interfaced with external packages, i.e. MC generators such as EvtGen. + +The decay products of a particle are enclosed within curly braces, for example +``` +K*(892)0{K+,pi-} +``` +describes an excited vector kaon decaying into a charged kaon and pion. +For more details about the API for describing particle decays, see [AmpGen::Particle](https://goofit.github.io/AmpGen/de/dd7/class_amp_gen_1_1_particle.html) +The other numbers on the lines that describe the decays parameterise the coupling to this channel, +either in terms of real and imaginary parts or an amplitude and a phase. +Each parameter is specified in terms of three numbers: the _fix_ flag, the initial value, and the step size. +The possible options for the _fix_ flag are: +* Free (fix=0) and a step size of not 0. +* Fixed (fix=2, for historical reasons) +* Compile-Time-Constant (fix=3) which indicates that the parameter should be treated as a (JIT) compile time constant, which in some cases allows for more aggressive optimisations to be performed. + +These options can be used in the Generator application, which is described below. + +Decays can either be specified fully inline, as above, or split into multiple steps, which is useful for treating the so called _cascade_ decays, an example of which is shown below. +``` +D0{K(1)(1270)+,pi-} 0 1 0.1 0 0 0.1 + +K(1)(1270)+{rho(770)0{pi+,pi-},K+} 2 1 0 2 0 0 +K(1)(1270)+{K*(892)0{K+,pi-},pi+} 0 1 0.1 0 0 0.1 +``` +The production/decay couplings of the $K_1(1270)^+$ resonance are now defined in terms of the coupling to the $\rho(770)^0 K^+$ channel, +which can be useful in making comparisons between different production modes of a resonance. +Additional care must be taken in such a case to not introduce redundant degrees of freedom. + +Configuration can be split over multiple files by the using _Import_ keyword, for example, to import the parameters for the isoscalar K-matrix, the line +``` +Import $AMPGENROOT/options/kMatrix.opt +``` + +can be added to options file. Multiple user configuration files can also be specified by including multiple files on the command line. + +## Applications +This section details the prebuilt command line applications that use the AmpGen library for some common functionality, such as generating Toy Monte Carlo samples +and debugging amplitudes. + +### Table of contents +* [Generator](#generator) +* [Debugger](#debugger) +* [ConvertToSourceCode](#converttosourcecode) + +### Generator + +The standalone generator for models can be used as + +```shell +Generator MyOpts.opt --nEvents=10000 --Output=output.root +``` + +Which generates 10000 events of the model described in MyOpts.opt and saves them to output.root. +The output should include a tree (DalitzEventList) of candidates with the full four-vectors, as well as one- and two-dimensional projections, an example of which is shown below: + +![s01](doc/figs/s01.png) + +In particular, the tree indicates the way in which data is by default loaded into the _Event_ / _EventList_ class. +Several models for different $D^0$ decays published by the LHCb collaboration are included in the options directory. These options do not include EventTypes so as they can be included as part of a larger decay chain if required. For example, to generate $10^6$ toy $D^{0}\to K^{-} \pi^+ \pi^+ \pi^- $ events: + +``` +./Generator options/D02Kpipipi.opt --EventType "D0 K- pi+ pi+ pi-" --nEvents 1000000 +``` + +### Debugger + +The debugger application is a tool for producing verbose information debugging for amplitudes and models. It is used on an options file as +``` +./Debugger MyOpts.opt +``` +which calculates each amplitude at a randomly generated point in phase space, as well as calculating the total amplitude accounting for complex +couplings. Also computed is the amplitude for the P conjugate event. A more useful application is the _verbose_ debugging mode which can be +activated by +``` +./Debugger MyOpts.opt --CoherentSum::Debug +``` +which produces a large number of intermediate steps in the calculation of each amplitude, which are added to the calculation using the +ADD_DEBUG and ADD_DEBUG_TENSOR macros in the code generation. For example, in src/Lineshapes/BW.cpp. +(n.b), if the model is a PolarisedSum, i.e. handles spin in the initial/final state, the flag PolarisedSum::Debug should be used instead of CoherentSum::Debug, in order +to generate all of the intermediate calculations of the amplitude. + +### ConvertToSourceCode + +This produces source code to evaluate the PDF, and normalises for use with other generators such as EvtGen, i.e. P(max) < 1. This can be used as +```shell +./ConvertToSourceCode MyOpts.opt --Output=MyFile.cpp +``` +This can then be a compiled to a shared library using +```shell +g++ -Ofast -shared -rdynamic --std=c++14 -fPIC MyFile.cpp -o MyFile.so +``` + +## Examples + +### SignalOnlyFitter + +An example fitter is provided in _examples/SignalOnlyFitter.cpp_, which as the name suggests only has a single signal component in the fit. +The free parameters of the fit are specified in the same way as the Generator, +with the additional relevant slots being _DataSample_ which specifies the signal sample to fit, +which is presumed to already have the selection applied, and _Branches_ which takes a list of branch names, +and defaults to the format used by the Generator etc. More details can be found with +``` +SignalOnlyFitter --help +``` +For example, the fitter can be used to fit a toy MC sample generated by the generator by running: +``` +Generator MyOpts.opt --nEvents 100000 +SignalOnlyFitter MyOpts.opt --DataSample Generate_Output.root +``` + +## Advanced + +This section contains miscellaneous details on more advanced functionality, including using python bindings and alternative parameterisation of the spin factors. + +### Table of contents +* [Python Bindings](#python-bindings) +* [Particle Properties and Lineshape parameters](#particle-properties-and-lineshape-parameters) +* [Fit parameters and expressions](#fit-parameters-and-expressions) +* [Spin Formalisms](#spin-formalisms) +* [Quasi-Particles](#quasi-particles) + +### Python Bindings +Models built into a shared library can be used in python using the following flags into ConvertToSourceCode: +```shell +./ConvertToSourceCode MyOpts.opt --Output=MyFile.cpp --OutputEvents=events.csv --IncludePythonBindings +``` +where normalisation events are also output for testing purposes in events.csv. +This can then be used with the python bindings in ampgen.py: +```python +from ampgen import FixedLib +model = FixedLib('MyModel.so') +print(model.matrix_elements[0]) # Print first matrix element + +import pandas as pd +data = pd.read_csv('events.csv', nrows=100_000) +fcn1 = model.FCN_all(data) + +# or, a bit slower, but just to show flexibility: +fcn2 = data.apply(model.FCN, axis=1) +``` + +### Particle Properties and Lineshape parameters +The particles available and their default properties can be found in *options/mass\_width.csv* using the MC format of the 2008 PDG. Additional pseudoparticles, such as nonresonant states and terms for use in conjunction with K-matrices are defined by *options/MintDalitzSpecialParticles.csv*. Any additional user defined particles should be added here. For the default lineshape (the relavistic Breit-Wigner or BW), there are three parameters: The mass, the width and the Blatt-Weisskopf radius. These default to their PDG values, but can be overridden in the options file with parameters: *particleName*\_mass, *particleName*\_width, *particleName*\_radius. To vary the mass of the $K_1(1270)^+$ meson, the line: +``` +K(1)(1270)+_mass 0 1.270 0.01 +``` +could be added to the user configuration. +Other lineshapes may define other parameters, for example channel couplings or pole masses in the case of the K-matrices, can be set or varied in a similar manner. + +### Fit parameters and expressions + +Parameters can either be specified by three parameters, in the case of a scalar parameter such as a mass or a width, or with six parameters in the case of a complex parameter such as a coupling. +Upper and lower bounds on parameters can also be set by specifying a parameter with five parameters or ten parameters for a scalar or complex, respectively. +For example, if we wished to vary the mass of the $K_1(1270)^+$ meson in the above example, but restricting the allowed values in the range $[0.0,2.0]\,\mathrm{GeV}$: +``` +K(1)(1270)+_mass 0 1.27 0.01 0.0 2.0 +``` + +Parameters can also be related to each other via expressions, +Suppose for example we have $K_1(1270)^+$ and $K_1(1270)^-$ in the same fit (for example, for $D^0 \to K^- K^+ \pi^- \pi^+$) +The properties of one can be allowed to vary, for example the $K_1(1270)^+$, and the other fixed to the same value, using: +``` +K(1)(1270)+_mass 0 1.27 0.01 0.0 2.0 +K(1)(1270)bar-_mass = K(1)(1270)+_mass +``` +Parameter expressions are whitespace delimited due to the abundance of **odd** glyphs such as brackets and +/- in the names of parameters. +Expressions support the binary operations $(+,-,/,* )$, as well as common unary functions such as sqrt, trigonometric functions etc. + +### Spin Formalisms + +AmpGen implements both the covariant tensor (or Rarita-Schwinger) and canonical helicity formalism for describing the angular momentum component of decays. +Both formalisms refer to states of well-defined orbital angular momentum, as opposed to the helicity states, as the states with well-defined orbital angular momentum have a straightforward parity and momentum dependences. +The default formalism is the covariant tensor formalism, but this can be switched to the canonical formalism changing the flag +``` +Particle::SpinFormalism Canonical ## default = Covariant +``` +in the options file. +The spin formalism for an individual decay chain can be specified by changing the attribute SpinFormalism in the decay descriptor. For example, +``` +D0[SpinFormalism=Canonical]{K*(892)bar0,rho(770)0} +``` +selects the S-wave of the $K^* \rho$ system. The user can also specify systems of helicity couplings in the canonical formalism, using the attribute _helAmp_. For example, suppose the transversity amplitudes were used rather than the canonical, then the user can specify +``` +D0[SpinFormalism=Canonical;helAmp=Long]{K*(892)bar0,rho(770)0} +D0[SpinFormalism=Canonical;helAmp=t1]{K*(892)bar0,rho(770)0} +D0[SpinFormalism=Canonical;helAmp=t2]{K*(892)bar0,rho(770)0} +``` +For the longitudinal and two transverse amplitudes. These must then be defined by the user in terms of the helicity amplitudes in the following structure: +``` +Long { + 1.0 0 0 +} + +t1 { + 0.707106781 +1 +1 + 0.707106781 -1 -1 +} + +t2 { + 0.707106781 +1 +1 + -0.707106781 -1 -1 +} +``` +That is specified as sets of three numbers, firstly the coupling, and then the two particle helicities. So in this example, the longitudinal amplitude is the $00$ helicity state, while the two transverse amplitudes and the sum and difference of the two other helicity amplitudes. + +### Quasi-Particles + + + +## Acknowledgements +The development of this software has been supported by the National Science Foundation under grant PHY-1414736 and through a subcontract under Cooperative Agreement OAC-1836650. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the developers and do not necessarily reflect the views of the National Science Foundation. + +

+

+ + + +
+

+ +[travis-badge]: https://travis-ci.org/GooFit/AmpGen.svg?branch=master +[license-badge]: https://img.shields.io/badge/License-GPL%20v2-blue.svg +[travis-link]: https://travis-ci.org/GooFit/AmpGen diff --git a/doc/figs/tex/fig0.png b/doc/figs/tex/fig0.png new file mode 100644 index 0000000000000000000000000000000000000000..d13cb4c9611a607e36a7e50b6284728c454cd108 GIT binary patch literal 688 zcmeAS@N?(olHy`uVBq!ia0vp^5kM@)0wfrg#Jv0pq?nSt-CY>?t&Hpz19_YU9+AaB zx&n;nevL{1GT2KzeO=ifvxzZCD1G#Oeu;sBalfaFV~EE2-plqLcLHP%d{lV4M0Dlk zxl!t|Iy<`f^sejW7K+5U=!UhwTFCC7!QajotF_B>`n<{AhdaCTwsVwquc(OiTHx#` zBjWE@9QWz%dsThItf*hg|9?C^{Ql|Rd)-I>A5)FkZoF>pp>=-AZ?r`Wyx%P(1 zvu-44EEG>xJg`~O?eShEY1hczSBsc-SN*#xbZ_y4*~xp} z6x>txPxsuj$o=kQALBh937MO3Clzcz*sG-XVq@C^@nuSPG>uP6$ZXAX*VLRg`Hb2< zX|CA#&BB#-{(zeXhh8SEvVzOL+#*~Azmls@`Czr?`6_}$aRF~s8Z)XC?wuQ-Stcb@39@@V~n z3zM6+%-B6WE+}f%jK#;3G#7cCmE&Sw`c}^6sPoN7t^$g-rTT~7Xl?BK{r|vk(Kna1i;ldq7LevB(P2n6E^SN&HzFz@TD zFwB9xozr$ja(rOy$m06*Yj*|n|JZ@ zMvslD52Dw7o3PA`Z7L)G+^H8$8#GT9wkK`Bus-$UE30!y+w{$Ei|w*1;D28?dr2LS zbY!~C<*hN@>vziCcf8x=-)8UlWv0AMp~=Lf@rUBGxEZGiu?zg*ZSXuX`=;Dfz;bBoe4 zJKkHoSfP2(@FSC~Ug>l>+e7D1mjB}PS9RRh{#f&#$z#dPl+J?rO0}Z)D{d{>n>UGl zvF5*Tf9L6jPRlv8{_>Nnn(oV4HkfVdj6d~Cp#IEmgGar!ht57(wa9$Ro^+8r46NJ# zZ;QyQ@Dr3f8UO8b(39+oe}kAZgEF2epXdH)Vfp#-)6?M*zw3MLpTA#yy1mJBKQL9O zmbgZgq$HN4S|t~y0x1R~14Bz)12bJC!w@4QD literal 0 HcmV?d00001 diff --git a/doc/figs/tex/fig10.png b/doc/figs/tex/fig10.png new file mode 100644 index 0000000000000000000000000000000000000000..d4547c8fc76f4bf002ce7b8d17fad1c2ee7e5aa3 GIT binary patch literal 716 zcmeAS@N?(olHy`uVBq!ia0vp^i-1^&1xPShEZ)8uNHHaOySp&(TN&9c2J$!yJR*yM zbOjjC{Th`3WU!Zb`ns||W)owO&=8!#cZPw1@wTUnV~EA+wIR0N%#H%QN=+Ucwrnu# zO{!~*ShiuqmcRh%jRJxG#}=G4ZJMgmlu)UevqmXm$%YF~NBlMh9DL;BsNEZPF2-(; z^mD!4)z#A_MCPPDfBRxr}~{>gsqjjGk{j_MMAUk7Og z#>|OkDmNcR2QYLUvG9K2c-!4rzvJEx=Z)Mif&O?dvG`$Zt;=E!rRR4#6K(b13T)6_ zeD|$UUwE*meNfU9k=ql@eq2ahbGfzAmFvl>Mb`trU(>qxI;cOA@9K-Yzb(nV^WM9FwH4DpNc6f&Evw}1mo77T zshBK~{^u3j!rp0zPp@43>(Ty0+Fs{hKCa-liI(~-aFlQ98|M!T^rS*AbJ;D{cF(rB zvc*!(UAA|}l5+}kR&gBjuRWb!@^puA)g{x=7wc~cPgu7Ww+c`Bxglugp{ac$_gut&?vNAHU zGBMCLFtRc*IGeLG4Mjt4eoAIqC2kFS3>j|$HHd(0C`d`O3QH|2&dkqa2yk)JHPkaz UV2$Cn1j;jby85}Sb4q9e0J$L{_W%F@ literal 0 HcmV?d00001 diff --git a/doc/figs/tex/fig11.png b/doc/figs/tex/fig11.png new file mode 100644 index 0000000000000000000000000000000000000000..38e8d29d6a2008bb4467fbc614b0e8754617b707 GIT binary patch literal 688 zcmeAS@N?(olHy`uVBq!ia0vp^5kM@)0wfrg#Jv0pq?nSt-CY>?t&Hpz19_YU9+AaB zx&n;nevL{1GT2KzeO=ifvxzZCXr|4#i(+74-0$h)7@~2$_p-gmodB5w9~GW15nVZX zZj^eg&W7?Hpy@D=K2W7C1Y~ zi1_;z$9;PHURB>PE9#f>{~u2ezkmAoUiZ=e$5bP>8?T#tXq{j38?DeZZ%fCzXurQD zO4H{%E_?Xk{GE_{5e-?26_5KJQUkKi_TPT8>1NK#e~D)kU$g1o{?YxgVXM*Z`7HGh zKWXN-hs>*$Vvey035nA@nEc^x&0T#hX74k``Wv1$3&oQa4{TO+d%Rak+BI_b)gq?dRsXIE-CO)%cJiJ# z1^1Nw(>?bra=$y-$9RuNLgwb%Nd?;v_A2SU*x0r}e3{Z6P2-aiGF$W9H8rPAKBIQe zxFWY;-^v3MzuFy{ztnm0Th?1T-rF6Q)tJ_1w0Aodb!XKSWM|90KHZ<+a=MoPw3}D= ztYY@vmN$*>d1&2xn)g&;-?B$9OJe^2&M%e!Z~c$q*6YyMT}*uJz}QtSag8WRNi0dV zN-jzTQVd20hL*YpX1Yd(Ax1`4MkZD!hS~;3Rt5&y(wi=!Xvob^$xN%ntwG9-D-Wna q1Y|=&N}5$zYEf}!ejY=Bi<_>Yo~Z(B47Vjvp25@A&t;ucLK6TI!Wo$W literal 0 HcmV?d00001 diff --git a/doc/figs/tex/fig12.png b/doc/figs/tex/fig12.png new file mode 100644 index 0000000000000000000000000000000000000000..00e1cad19b3bf511d5c10b588266a77f890143ad GIT binary patch literal 565 zcmeAS@N?(olHy`uVBq!ia0vp^Q9vxl0wfp~th77?t&Hpz19_YU9+AaB zx&n;nevL{1GT2KzeO=ifvxzZCX#Jm-|A2vk(Z$onF+}5h@(+KmgdhLw`Rsnq=17zG z`1-!CX4PteGwBLf{XgEy?N9i(j(ycRHskBb;eVFPbw2(*|KWVQ8BhCTzkdJhF(>uE zWZkvL!GBqgRj?nC|8HCq+wcFiNMf z58Ypyt{?UPf3CP$ZrZ+Q~ zIPBlozN+q>75_S^<=zQ~--C-wAJ-6Urv1Z|NPGa(Gx$Jj;v!etUKVcZ!i1PEv6Qm zoou-H=Unz+WcdDOfzP39SCxT5tXkq4QIe8al4_M)lnSI6j0_Adbq&mPjSNGKjI4}I ztW1ow4UDV|45B`-@JG>*o1c=IR*74K_Bw&jKn)@w8wyg=tin=@iZk=`7y?|}bPe@P U6zopr08Fy$egFUf literal 0 HcmV?d00001 diff --git a/doc/figs/tex/fig13.png b/doc/figs/tex/fig13.png new file mode 100644 index 0000000000000000000000000000000000000000..3bcb1cc7a9489019aa7dfe371eed04e434ad9450 GIT binary patch literal 450 zcmeAS@N?(olHy`uVBq!ia0vp^%0Mi{0wfp=Q?B*^DW)WEcNYeJD(j(p$n@ z8uc$+kiMcE;_UbEl1Qtw3D>0?Mcbu58{R6(DqS5IxItx4efaLMC;Z=we(239)??hp z=#uT=KCgk{G^2UrzpNh%H4DU^u67wlv&Hfr(D}`%IkQ+k=ht8uPLi1*&7!o ziQR13kscP9(*3(bpv>^&(hqEp7!Rgyn7PEo)kG~q&M7o#&Ec&Y(b_A$xg^b!l7hEr z{My~~ohd5h+Kvl>^b(W9OyaK z64!{5l*E!$tK_0oAjM#0U}&jpV5Vzi7-D2(Wn^MyVx(5CPdxkdkHbP0l+XkKV2YtV literal 0 HcmV?d00001 diff --git a/doc/figs/tex/fig14.png b/doc/figs/tex/fig14.png new file mode 100644 index 0000000000000000000000000000000000000000..aa02a85116eef75c96d810c6b1a8277054cf06a5 GIT binary patch literal 342 zcmeAS@N?(olHy`uVBq!ia0vp^B0$W~0wfq%m}5JD6jPG7y9)!qm66?IAdj=aBeEDs zSAg-{uTcp=278I8uPggwHZcYX?T(4@Wk8`+PZ!4!j_b0gHu5$xFtA>{Kl21b*}24w zj47fr2m1sxZXUhF7<1%E#D$G*f+sxJRqlMmbh@SG{)ZVVdm^2OC7#SE^>Kd5o8X1Nd8Ce;bSeY1W8yHy`82o8j{2N6>ZhlH;S|x4`y*H)Zff__W pHWZ|!S%sw*6=&w>F$B1{=^E;pDzL_ITLR@7JYD@<);T3K0RT0}X{Z1I literal 0 HcmV?d00001 diff --git a/doc/figs/tex/fig2.png b/doc/figs/tex/fig2.png new file mode 100644 index 0000000000000000000000000000000000000000..17fa75658034301fc889fdeb11d4c8d21e413079 GIT binary patch literal 404 zcmeAS@N?(olHy`uVBq!ia0vp^;y^6K0wfp$YQCQXQcOwS?k)`cRz`M-{(zeXhh8SEvVzOL+#*~Azml-s_;l6_#35oSC1;5a8mbYp7?cz#7AC36y8>boFyt=akR{ E0JaR3s{jB1 literal 0 HcmV?d00001 diff --git a/doc/figs/tex/fig3.png b/doc/figs/tex/fig3.png new file mode 100644 index 0000000000000000000000000000000000000000..5d646ca2dc6eca90047c63d7e7e7e735b4fe34f0 GIT binary patch literal 406 zcmeAS@N?(olHy`uVBq!ia0vp^(m*W40wfr`9K;=f6jPG7y9)!qm66?IAdj=aBeEDs zSAg-{uTcp=278I8uPggwHZcYX6$w43=Rl#Qo-U3d5|@*I@U!pV{k%TGpA(Fq`zQaS8B_N& z?0gAS`1jiX_k2&g{{MgfE&knpzA2~w{@;K4|I^#goppbp!`2Syb!j9Sh{!eW#*stDo_22)AKM1xPTgag}ofQcOwS?k)`cRz`M-{(zeXhh8SEvVzOL+#*~AzmR3!AAo-;5oUiNfx46!)9HpJFjIZ%XGsY&PHr9)A( zML%;NF=}mH+S|0dH=<)lUrcjaymEwROvDD6?%Zub8$1#hwsypdaVzIcbamABHS6n} zJVWOFnLYexqZ6C&J)2jq_kPcB)5#56o_z}6b5o16b>YlhvqEp>n3loA0h(`bUc#tL`j}(OF)g zQ$9aw|I>YEs?^H9H@}XZmHni~W&4l2#vSb)%?CHel=l6d^6GY6&Tiq0D}M>jFL9Ut zFnd+5YKQiX8Bgm9lg`G8MlU|`%zd%&@v?bO|88ElJfQgV2E)^>+0Xg6^5jRYi{-pJ zB~e{|%bnOvUbD2F1#kCltyyQf@VefQgjv%+ZN0!`cf=^MyKXs zzlKjlL$7w{QNN?t&Hpz19_YU9+AaB zx&n;nevL{1GT2KzeO=ifvxzZCsOD=H6*4d|?)P+Y4AD5>d)eOOPJqmTj|xwhh_0MG zH%dKLXGa&G-gUj)LXj93-LUpo3)%fM_}lqnwRU+{6&0~w3!EKg zMEw1V<37E8uc~jD74=K`|Bt7K-#`6(ulwl#W2zC`jn~aRw9YU2jaF!yx20oUwBO$n zrRnn>mpy!N{!Ylfh=wf1ipTv9sR3DM`)@zlbTen=zr?eNui5l(|LA_$u+?bye3tr$ zpEUE^L*~^=F~?Yhgv4ncO#X1U=B~b_KFj`t`DvVXpZI>QIDcg7?j3rPdy+md*WNIh zR>7pdQ2Ee3XU&A98xKlPw7id2;9mbIZ_B^D-h%xH1H@e$vv;07n9`DcUffu)PUi8d zEhpr83izg^*z}&?EqOI|{S8l>h2qJI2R19ZJ>IJ%?HalJY7x`!s()97?k#>WJ9*EW zf_uvT>7IKQx!;}aW4y;BA#?NXq=M}SdzJKFY;0Q~zD((krtwJ$nXP&5nwrxlpHaJK zT#;L_Z{>lBU+s>}U+TR0E$b~E@9mDuYD{Z0+Pj^Ky0dBuva{u0pYG3ZIbF+t+Rdwb zRx$f-%bUjcJhbjT&3me_Z`q@lB{Bbh=avibsE+#&9VC<@vxJHzuB$lLF zB^RXvDF!10LrYx)GhHLY5F;ZiBNHoQb8Q17D+2>2zP^tr8glbfGSez?YbXvj^95=U q0ohQHl4cc_T2!2wpT`j3;-+h;XR5#&!)*zaXYh3Ob6Mw<&;$UYP8o9m literal 0 HcmV?d00001 diff --git a/doc/figs/tex/fig6.png b/doc/figs/tex/fig6.png new file mode 100644 index 0000000000000000000000000000000000000000..18c7e5b04ad7e2a144bdc2c3514fd07a08e80528 GIT binary patch literal 688 zcmeAS@N?(olHy`uVBq!ia0vp^5kM@)0wfrg#Jv0pq?nSt-CY>?t&Hpz19_YU9+AaB zx&n;nevL{1GT2KzeO=ifvxzZCsC`pVKFz?uxZl&oF+}5h?`3+TEoAr4;BV)P)!OAbect5m!=2rE+d0a*S5(A$EpT>} z5%Kpcj{EfXy{f)pR@5)$|397{e*g6Ez3!v`kEup%H(odQ&^o{5H(H@--j^*20i7K$e;9@wnt_IR(7v}@${Zfxv9WD|_%fwCn#Lz3WVYtHYidrLd`9h_ zaYb&yzLf_ieziL?f2s50x2(5xytg|pt1+$3Xzz9^>dvYu$j+8~eY!ut<#a9oX*aL# zS;g$TEpHm%^U%8YH1DaxzGaVImc;!3onI>d-})cJt=FNiyO{Xcfw8Mv;u=wsl30>z zm0Xkxq!^403@vpH%yf+mLyU~9j7+SIEwl}ctPBjkxc!qr(U6;;l9^VCTSKd~+Y+D# q5s(c9DQQ+=sYS(^`FRWhE^fMpdZr4jG2E6wc?M5cKbLh*2~7Y#o*MxG literal 0 HcmV?d00001 diff --git a/doc/figs/tex/fig7.png b/doc/figs/tex/fig7.png new file mode 100644 index 0000000000000000000000000000000000000000..e6e17b7a8f71304b710abaf145be98225632e4f6 GIT binary patch literal 761 zcmeAS@N?(olHy`uVBq!ia0vp^1wbsu0wfrITw8S!NHHaOySp&(TN&9c2J$!yJR*yM zbOjjC{Th`3WU!Zb`ns||W)owOQ2VB!d>W{U!_&nv#NzbaDfSs6jv~jlTc40+>DGvd z@LIFYN8qD?iJ8+H9u}3dm6J}-Pda!wN11aali00}jh{~OUiT16;no)1sUh|f9ChJduv)1XN%soyFTyEFLjSt{Q&v-TO#&2 z$9JTBc-$y_=H!dk&n>$f4sQA9cH-E*rcd`H_A@GT%;;l2w_?^8CypchsYmr+gnFLJ z-6I~oz4hq<4yJcM4y4C|4#|oJ*koV1VbjSzfyjE zl}DQN7L$2j^N&B&-uP^`%5vuLc2?F$Z@u3c@8rppm&y4UfB$0T_reXeGGcdr2OC7#SE^>Kd5o8X1Nd8Ce;bSQ%Sr z8yHy`7<_U2CxN0NH$NpatrE9}R%y2-Kn)@w8wyg=tin=@iZk=`7y?|}bPe@P6zopr0CC?sQvd(} literal 0 HcmV?d00001 diff --git a/doc/figs/tex/fig8.png b/doc/figs/tex/fig8.png new file mode 100644 index 0000000000000000000000000000000000000000..60ac3e54c3440050403923e9090f3fc7631881a3 GIT binary patch literal 688 zcmeAS@N?(olHy`uVBq!ia0vp^5kM@)0wfrg#Jv0pq?nSt-CY>?t&Hpz19_YU9+AaB zx&n;nevL{1GT2KzeO=ifvxzZCs5hz$$1*T5?)P+Y4AD5>d)eOOPJqmTj|xwhh_0MG zH%dKLXGa&G-gUj)LXj93-LUpo3)%fM_}lqnwRU+{6&0~w3!EKg zMEw1V<37E8uc~jD74=K`|Bt7K-#`6(ulwl#W2zC`jn~aRw9YU2jaF!yx20oUwBO$n zrRnn>mpy!N{!Ylfh=wf1ipTv9sR3DM`)@zlbTen=zr?eNui5l(|LA_$u+?bye3tr$ zpEUE^L*~^=F~?Yhgv4ncO#X1U=B~b_KFj`t`DvVXpZI>QIDcg7?j3rPdy+md*WNIh zR>7pdQ2Ee3XU&A98xKlPw7id2;9mbIZ_B^D-h%xH1H@e$vv;07n9`DcUffu)PUi8d zEhpr83izg^*z}&?EqOI|{S8l>h2qJI2R19ZJ>IJ%?HalJY7x`!s()97?k#>WJ9*EW zf_uvT>7IKQx!;}aW4y;BA#?NXq=M}SdzJKFY;0Q~zD((krtwJ$nXP&5nwrxlpHaJK zT#;L_Z{>lBU+s>}U+TR0E$b~E@9mDuYD{Z0+Pj^Ky0dBuva{u0pYG3ZIbF+t+Rdwb zRx$f-%bUjcJhbjT&3me_Z`q@lB{Bbh=avibsE+#&9VC<@vxJHzuB$lLF zB^RXvDF!10LrYx)GhHLY5F;ZiBNHoQOKk%qD+7Zd!>?;lH00)|WTsW()}Wl@D*)6W q0?t&Hpz19_YU9+AaB zx&n;nevL{1GT2KzeO=ifvxzZCXb8^WJHx=hxXIJSF+}71)XVldDuFTwK6akqQd+*q z>FKP!PofrH(BWM)B}TcgAUvTtg+sd4$@zs#a_Du9Fq4wo9%1H(p2jFojw$SnDNIV8 zxz#v+zxll$#mOD<&(2rt&#yFo|Ghf-L!UuhnXLA)JOBANCeNzm^S%9E?&Qj-|4)iu z_J`!`dHH&{_GW7_g+A^oaMAzSNEj9T-KR4jo%gM z=pFg5d3$4pmfZCFKi1w8>=$Vd3;AoSHys$EswJ)wB`Jv|saDBFsX&Us$iUE2*T78I z$S}mn$jZpX%EUn1z{twL;B3y$G!zZF`6-!cmAEzRF=V_2)F1+~p&%vADlE0AI5R(w cA;85=*HF(?fi;HP5-88$>FVdQ&MBb@0M{T7AOHXW literal 0 HcmV?d00001 diff --git a/src/OptionsParser.cpp b/src/OptionsParser.cpp index 789d8c0ee62..74cfab93f20 100644 --- a/src/OptionsParser.cpp +++ b/src/OptionsParser.cpp @@ -155,7 +155,7 @@ bool OptionsParser::printHelp() { return getMe()->m_pri void OptionsParser::setArgs( int argc, char** argv , const std::string& description){ getMe()->setCommandLineArgs(argc, argv, description); } void OptionsParser::setArg( const std::string& arg ){ getMe()->addArg( arg ); } OptionsParser::iterator OptionsParser::find( const std::string& name ) { return m_parsedLines.find( name ); } -OptionsParser::iterator OptionsParser::begin() { return m_parsedLines.begin(); } -OptionsParser::iterator OptionsParser::end() { return m_parsedLines.end(); } +OptionsParser::iterator OptionsParser::begin() { return m_parsedLines.begin(); } +OptionsParser::iterator OptionsParser::end() { return m_parsedLines.end(); } OptionsParser::const_iterator OptionsParser::begin() const { return m_parsedLines.cbegin(); } -OptionsParser::const_iterator OptionsParser::end() const { return m_parsedLines.cend(); } +OptionsParser::const_iterator OptionsParser::end() const { return m_parsedLines.cend(); } diff --git a/src/Particle.cpp b/src/Particle.cpp index 30eb7a0a5f6..00fc6963988 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -326,7 +326,8 @@ Expression Particle::propagator( DebugSymbols* db ) const else if ( m_daughters.size() == 1 && m_lineshape != "BW" && m_lineshape != "FormFactor" ) { std::vector p_vector; - for( auto& d : m_daughters[0]->daughters() ) p_vector.emplace_back( d->P() ); + auto fs = getFinalStateParticles(true); + for( auto& d : fs ) p_vector.emplace_back( d->P() ); prop = Lineshape::Factory::get(m_lineshape, massSq(), p_vector, m_name, m_orbital, db ); } total = total * make_cse(prop); From 18d936abcf454d331cde848e5765bcd2131e5042 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sat, 22 Jun 2019 10:11:16 +0200 Subject: [PATCH 077/250] Make doxygen variant of markdown work correctly for intro --- README.tex.md | 20 +++++++++++--------- doc/doxyfile | 4 ++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/README.tex.md b/README.tex.md index 2cbb754f4f1..d63604095d0 100644 --- a/README.tex.md +++ b/README.tex.md @@ -125,7 +125,7 @@ D0{K(1)(1270)+,pi-} 0 1 0.1 0 0 K(1)(1270)+{rho(770)0{pi+,pi-},K+} 2 1 0 2 0 0 K(1)(1270)+{K*(892)0{K+,pi-},pi+} 0 1 0.1 0 0 0.1 ``` -The production/decay couplings of the $K_1(1270)^+$ resonance are now defined in terms of the coupling to the $\rho(770)^0 K^+$ channel, +The production/decay couplings of the @f$K_1(1270)^+@f$ resonance are now defined in terms of the coupling to the @f$\rho(770)^0 K^+@f$ channel, which can be useful in making comparisons between different production modes of a resonance. Additional care must be taken in such a case to not introduce redundant degrees of freedom. @@ -156,10 +156,12 @@ Generator MyOpts.opt --nEvents=10000 --Output=output.root Which generates 10000 events of the model described in MyOpts.opt and saves them to output.root. The output should include a tree (DalitzEventList) of candidates with the full four-vectors, as well as one- and two-dimensional projections, an example of which is shown below: -![s01](doc/figs/s01.png) +

+ +

In particular, the tree indicates the way in which data is by default loaded into the _Event_ / _EventList_ class. -Several models for different $D^0$ decays published by the LHCb collaboration are included in the options directory. These options do not include EventTypes so as they can be included as part of a larger decay chain if required. For example, to generate $10^6$ toy $D^{0}\to K^{-} \pi^+ \pi^+ \pi^- $ events: +Several models for different @f$D^0@f$ decays published by the LHCb collaboration are included in the options directory. These options do not include EventTypes so as they can be included as part of a larger decay chain if required. For example, to generate @f$10^6@f$ toy @f$D^{0}\to K^{-} \pi^+ \pi^+ \pi^- @f$ events: ``` ./Generator options/D02Kpipipi.opt --EventType "D0 K- pi+ pi+ pi-" --nEvents 1000000 @@ -243,7 +245,7 @@ fcn2 = data.apply(model.FCN, axis=1) ``` ### Particle Properties and Lineshape parameters -The particles available and their default properties can be found in *options/mass\_width.csv* using the MC format of the 2008 PDG. Additional pseudoparticles, such as nonresonant states and terms for use in conjunction with K-matrices are defined by *options/MintDalitzSpecialParticles.csv*. Any additional user defined particles should be added here. For the default lineshape (the relavistic Breit-Wigner or BW), there are three parameters: The mass, the width and the Blatt-Weisskopf radius. These default to their PDG values, but can be overridden in the options file with parameters: *particleName*\_mass, *particleName*\_width, *particleName*\_radius. To vary the mass of the $K_1(1270)^+$ meson, the line: +The particles available and their default properties can be found in *options/mass\_width.csv* using the MC format of the 2008 PDG. Additional pseudoparticles, such as nonresonant states and terms for use in conjunction with K-matrices are defined by *options/MintDalitzSpecialParticles.csv*. Any additional user defined particles should be added here. For the default lineshape (the relavistic Breit-Wigner or BW), there are three parameters: The mass, the width and the Blatt-Weisskopf radius. These default to their PDG values, but can be overridden in the options file with parameters: *particleName*\_mass, *particleName*\_width, *particleName*\_radius. To vary the mass of the @f$K_1(1270)^+@f$ meson, the line: ``` K(1)(1270)+_mass 0 1.270 0.01 ``` @@ -254,20 +256,20 @@ Other lineshapes may define other parameters, for example channel couplings or p Parameters can either be specified by three parameters, in the case of a scalar parameter such as a mass or a width, or with six parameters in the case of a complex parameter such as a coupling. Upper and lower bounds on parameters can also be set by specifying a parameter with five parameters or ten parameters for a scalar or complex, respectively. -For example, if we wished to vary the mass of the $K_1(1270)^+$ meson in the above example, but restricting the allowed values in the range $[0.0,2.0]\,\mathrm{GeV}$: +For example, if we wished to vary the mass of the @f$K_1(1270)^+@f$ meson in the above example, but restricting the allowed values in the range @f$[0.0,2.0]\,\mathrm{GeV}@f$: ``` K(1)(1270)+_mass 0 1.27 0.01 0.0 2.0 ``` Parameters can also be related to each other via expressions, -Suppose for example we have $K_1(1270)^+$ and $K_1(1270)^-$ in the same fit (for example, for $D^0 \to K^- K^+ \pi^- \pi^+$) -The properties of one can be allowed to vary, for example the $K_1(1270)^+$, and the other fixed to the same value, using: +Suppose for example we have @f$K_1(1270)^+@f$ and @f$K_1(1270)^-@f$ in the same fit (for example, in @f$D^0 \to K^- K^+ \pi^- \pi^+@f$) +The properties of one can be allowed to vary, for example the @f$K_1(1270)^+@f$, and the other fixed to the same value, using: ``` K(1)(1270)+_mass 0 1.27 0.01 0.0 2.0 K(1)(1270)bar-_mass = K(1)(1270)+_mass ``` Parameter expressions are whitespace delimited due to the abundance of **odd** glyphs such as brackets and +/- in the names of parameters. -Expressions support the binary operations $(+,-,/,* )$, as well as common unary functions such as sqrt, trigonometric functions etc. +Expressions support the binary operations @f$(+,-,/,* )@f$, as well as common unary functions such as sqrt, trigonometric functions etc. ### Spin Formalisms @@ -282,7 +284,7 @@ The spin formalism for an individual decay chain can be specified by changing th ``` D0[SpinFormalism=Canonical]{K*(892)bar0,rho(770)0} ``` -selects the S-wave of the $K^* \rho$ system. The user can also specify systems of helicity couplings in the canonical formalism, using the attribute _helAmp_. For example, suppose the transversity amplitudes were used rather than the canonical, then the user can specify +selects the S-wave of the @f$K^* \rho@f$ system. The user can also specify systems of helicity couplings in the canonical formalism, using the attribute _helAmp_. For example, suppose the transversity amplitudes were used rather than the canonical, then the user can specify ``` D0[SpinFormalism=Canonical;helAmp=Long]{K*(892)bar0,rho(770)0} D0[SpinFormalism=Canonical;helAmp=t1]{K*(892)bar0,rho(770)0} diff --git a/doc/doxyfile b/doc/doxyfile index c7320a0781b..f9b12378de2 100644 --- a/doc/doxyfile +++ b/doc/doxyfile @@ -38,8 +38,8 @@ PROJECT_BRIEF = PROJECT_LOGO = "figs/logo_small.png" LAYOUT_FILE = "DoxygenLayout.xml" HTML_EXTRA_STYLESHEET = "customdoxygen.css" -INPUT = "../AmpGen" "../README.md" -USE_MDFILE_AS_MAINPAGE = "../README.md" +INPUT = "../AmpGen" "../README.tex.md" +USE_MDFILE_AS_MAINPAGE = "../README.tex.md" IMAGE_PATH = "figs/" # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- From 1daecdb86ba32572ae2da46ed28828b5e6901c20 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 8 Jul 2019 15:26:48 +0200 Subject: [PATCH 078/250] Fix quantum numbers of the X(3872), add generators of SU(3) for beginnings of vector production polarisation implementation, improvements in generalised lineshape interface --- AmpGen/DiracMatrices.h | 1 + AmpGen/Lineshapes.h | 71 +++++++++++--------- AmpGen/Particle.h | 4 +- AmpGen/ParticleProperties.h | 10 +-- AmpGen/PolarisedSum.h | 2 +- AmpGen/Vertex.h | 4 +- examples/QcGenerator.cpp | 6 +- options/mass_width.csv | 2 +- src/DiracMatrices.cpp | 19 ++++-- src/Lineshapes.cpp | 7 +- src/Lineshapes/BW.cpp | 1 + src/Lineshapes/EtaDalitz.cpp | 15 +++-- src/Particle.cpp | 50 +++++++------- src/ParticleProperties.cpp | 9 +-- src/ParticlePropertiesList.cpp | 2 +- src/PolarisedSum.cpp | 115 ++++++++++++++++++--------------- src/QuarkContent.cpp | 5 +- src/Vertex.cpp | 5 +- src/Wigner.cpp | 6 +- 19 files changed, 184 insertions(+), 150 deletions(-) diff --git a/AmpGen/DiracMatrices.h b/AmpGen/DiracMatrices.h index 69ce55aaf25..4ccd1330830 100644 --- a/AmpGen/DiracMatrices.h +++ b/AmpGen/DiracMatrices.h @@ -13,6 +13,7 @@ namespace AmpGen extern const std::array Gamma; extern const std::array Sigma; extern const std::array S03; + extern const std::array SU3; } // namespace AmpGen #endif diff --git a/AmpGen/Lineshapes.h b/AmpGen/Lineshapes.h index dbb2d554f81..d9a1dcf095a 100644 --- a/AmpGen/Lineshapes.h +++ b/AmpGen/Lineshapes.h @@ -10,6 +10,8 @@ #include "AmpGen/Factory.h" #include "AmpGen/MsgService.h" #include "AmpGen/Tensor.h" +#include "AmpGen/Particle.h" + /** @defgroup Lineshapes Lineshapes @brief Lineshapes are semi-empirical complex functions for describing the propagation and decay of short-lived resonances. @@ -47,38 +49,37 @@ const AmpGen::Expression& s2, const std::string& particleName, \ const unsigned int& L, const std::string& lineshapeModifier, \ AmpGen::DebugSymbols* dbexpressions = 0) const override; \ - AmpGen::Expression get(const AmpGen::Expression& s, const std::vector& p, \ - const std::string& particleName, \ - const unsigned int& L, const std::string& lineshapeModifier, \ + AmpGen::Expression get(const AmpGen::Particle& p, \ + const std::string& lineshapeModifier, \ AmpGen::DebugSymbols* dbexpressions = nullptr ) const override; \ } #define DEFINE_LINESHAPE( X ) \ - REGISTER_WITH_KEY( Lineshape::Base, Lineshape::X, #X, std::string ); \ - AmpGen::Expression Lineshape::X::get( const AmpGen::Expression& s, const std::vector& p, \ - const std::string& particleName, \ - const unsigned int& L, const std::string& lineshapeModifier, \ + REGISTER_WITH_KEY( Lineshape::Base, Lineshape::X, #X, std::string ); \ + AmpGen::Expression Lineshape::X::get( const AmpGen::Particle& p, \ + const std::string& lineshapeModifier, \ AmpGen::DebugSymbols* dbexpressions ) const { return \ - get(s, dot(p[0],p[0]), dot(p[1],p[1]), \ - particleName, L, lineshapeModifier, dbexpressions) ;} \ + get(p.massSq(), p.daughter(0)->massSq(), p.daughter(1)->massSq(), \ + p.name(), p.orbital(), lineshapeModifier, dbexpressions) ;} \ AmpGen::Expression Lineshape::X::get( const AmpGen::Expression& s, const AmpGen::Expression& s1, \ const AmpGen::Expression& s2, const std::string& particleName, \ const unsigned int& L, const std::string& lineshapeModifier, \ AmpGen::DebugSymbols* dbexpressions ) const #define DEFINE_GENERIC_SHAPE( X ) \ - REGISTER_WITH_KEY( Lineshape::Base, Lineshape::X, #X, std::string ); \ + REGISTER_WITH_KEY( Lineshape::Base, Lineshape::X, #X, std::string ); \ AmpGen::Expression Lineshape::X::get( const AmpGen::Expression& s, const AmpGen::Expression& s1, \ const AmpGen::Expression& s2, const std::string& particleName, \ const unsigned int& L, const std::string& lineshapeModifier, \ AmpGen::DebugSymbols* dbexpressions ) const { return 0;} \ - AmpGen::Expression Lineshape::X::get( const AmpGen::Expression& s, const std::vector& p, \ - const std::string& particleName, \ - const unsigned int& L, const std::string& lineshapeModifier, \ + AmpGen::Expression Lineshape::X::get( const AmpGen::Particle& p, \ + const std::string& lineshapeModifier, \ AmpGen::DebugSymbols* dbexpressions ) const namespace AmpGen { + class Particle; // forward definitions + /** @ingroup Lineshapes namespace Lineshape Namespace that contains all lineshapes, i.e. propagators for describing amplitudes and phases for resonances (and nonresonant) contributions to a total amplitude. */ @@ -91,8 +92,8 @@ namespace AmpGen virtual Expression get( const Expression& s, const Expression& s1, const Expression& s2, const std::string& particleName, const unsigned int& L, const std::string& lineshapeModifier, DebugSymbols* dbexpressions = nullptr ) const = 0; - virtual Expression get( const Expression& s, const std::vector& p, const std::string& particleName, - const unsigned int& L, const std::string& lineshapeModifier, + virtual Expression get( const AmpGen::Particle& p, + const std::string& lineshapeModifier, AmpGen::DebugSymbols* dbexpressions = nullptr ) const = 0; Base* create() { return this; } }; @@ -104,9 +105,8 @@ namespace AmpGen const Expression& s2, const std::string& particleName, const unsigned int& L, std::vector>* dbexpressions = nullptr ); static Expression get(const std::string& lineshape, - const Expression& s, - const std::vector& p, const std::string& particleName, - const unsigned int& L, AmpGen::DebugSymbols* dbexpressions ); + const Particle& p, + AmpGen::DebugSymbols* dbexpressions ); static bool isLineshape( const std::string& lineshape ); }; @@ -151,7 +151,16 @@ namespace AmpGen @f$\Gamma_0@f$ | particleName_width | Breit-Wigner width, defined as the width of resonance at the Breit-Wigner mass */ DECLARE_LINESHAPE( SBW ); - /// Non-relativistic Breit-Wigner lineshape + + /** @ingroup Lineshapes class NonRelBW + @brief Nonrelativistic Breit-Wigner lineshape + + Non-relativistic Breit-Wigner lineshape, given by + + @f[ + \mathcal{A}(s) = \sqrt{ \frac{ \Gamma_0 }{ 2 \pi } } \left( \sqrt{s} - m_0 - i \Gamma_0 /2 \right)^{-1} + @f] + */ DECLARE_LINESHAPE( NonRelBW ); /** @ingroup Lineshapes class GounarisSakurai @@ -251,16 +260,16 @@ namespace AmpGen @f] that is, the 'resonant' and 'nonresonant' phases of the LASS formulation with additional 'proudction' phases @f$ \phi_R @f$ and @f$\phi_F @f$, and production couplings @f$R, F@f$. One of the production couplings can typically be fixed to 1, normally the resonant coupling, @f$R @f$. - Parameter | User name | Description - -----------------------|----------------------------------|------------------------------------------------------------------------ - @f$m@f$ | particleName_mass | Breit-Wigner mass of the resonant component, defined as energy at which the self-energy of the resonance is purely imaginary (defaults to value in PDG)
- @f$\Gamma_0@f$ | particleName_width | Breit-Wigner width of the resonant component, defined as the width of resonance at the Breit-Wigner mass
- @f$a@f$ | particleNameGLASSa | Scattering length of the nonresonant component, defaults to @f$2.07\mathrm{G\kern -0.1em eV}^{-1}@f$ - @f$r@f$ | particleNameGLASSr | Effective interaction length of the nonresonant component, defaults to @f$3.32\mathrm{G\kern -0.1em eV}^{-1}@f$ - @f$\phi_R@f$ | particleNameGLASSphiR | Additional production phase of the resonant component, defaults to @f$0^{\mathrm{o}}@f$, measured in degrees. - @f$\phi_F@f$ | particleNameGLASSphiF | Additional production phase of the nonresonant component, defaults to @f$0^{\mathrm{o}}@f$, measured in degrees. - @f$R@f$ | particleNameGLASSR | Additional production coupling of the resonant component, defaults to @f$1@f$. - @f$F@f$ | particleNameGLASSF | Additional production coupling of the nonresonant component, defaults to @f$1@f$. + Parameter | Interface parameter name | Description + -----------------------|--------------------------------------|------------------------------------------------------------------------ + @f$m@f$ | particleName_mass | Breit-Wigner mass of the resonant component, defined as energy at which the self-energy of the resonance is purely imaginary (defaults to value in PDG)
+ @f$\Gamma_0@f$ | particleName_width | Breit-Wigner width of the resonant component, defined as the width of resonance at the Breit-Wigner mass
+ @f$a@f$ | particleName::GLASS::a | Scattering length of the nonresonant component, defaults to @f$2.07\mathrm{G\kern -0.1em eV}^{-1}@f$ + @f$r@f$ | particleName::GLASS::r | Effective interaction length of the nonresonant component, defaults to @f$3.32\mathrm{G\kern -0.1em eV}^{-1}@f$ + @f$\phi_R@f$ | particleName::GLASS::phiR | Additional production phase of the resonant component, defaults to @f$0^{\mathrm{o}}@f$, measured in degrees. + @f$\phi_F@f$ | particleName::GLASS::phiF | Additional production phase of the nonresonant component, defaults to @f$0^{\mathrm{o}}@f$, measured in degrees. + @f$R@f$ | particleName::GLASS::R | Additional production coupling of the resonant component, defaults to @f$1@f$. + @f$F@f$ | particleName::GLASS::F | Additional production coupling of the nonresonant component, defaults to @f$1@f$. */ DECLARE_LINESHAPE(GLASS); @@ -303,7 +312,7 @@ namespace AmpGen which is potentially useful for fitting very long-lived contributions that are essentially limited by the experimental resolution, rather than the natural lifetime. This type of parameterisation will assess contributions from interference incorrectly. - Parameter | User name | Description + Parameter | Interface parameter name | Description -----------------------|--------------------------------------|------------------------------------------------------------------------ @f$\mu@f$ | lineshapeModifier_mean | Mean of the gaussian distribution. @f$\sigma@f$ | lineshapeModifier_sigma | Width of the gaussian distribution. @@ -341,7 +350,7 @@ namespace AmpGen @f] where @f$a_n@f$ is the value of the function evaluated at the @f$ n @f$ knot and the other polynomial coefficients are determined by imposing continuity and differentiability. - Parameter | User name | Description + Parameter | Interface parameter name | Description -----------------------|--------------------------------------|------------------------------------------------------------------------ @f$\mathcal{R}(a_j)@f$ | particleName::Spline::Re::j | The real value of the lineshape evaluated at the @f$ j @f$th knot. @f$\mathcal{I}(a_j)@f$ | particleName::Spline::Im::j | The imaginary value of the lineshape evaluated at the @f$ j @f$th knot. diff --git a/AmpGen/Particle.h b/AmpGen/Particle.h index 50b410359f9..fb2d33668f7 100644 --- a/AmpGen/Particle.h +++ b/AmpGen/Particle.h @@ -155,7 +155,6 @@ namespace AmpGen bool isStable() const; bool isQuasiStable() const; bool conservesParity( unsigned int L = 0 ) const; - bool checkExists() const; unsigned int orbital() const; unsigned int index() const; @@ -202,6 +201,9 @@ namespace AmpGen /// Returns in indexth decay product of this particle (as constant) std::shared_ptr daughter( const size_t& index ) const; + + /// Returns in indexth decay product of this particle (as constant) + std::shared_ptr daughter(const std::string& name, const int& maxDepth=-1) const; /// Vector of decay products of this particle std::vector> daughters() const; diff --git a/AmpGen/ParticleProperties.h b/AmpGen/ParticleProperties.h index 02766797f00..d2ce1e921de 100644 --- a/AmpGen/ParticleProperties.h +++ b/AmpGen/ParticleProperties.h @@ -20,15 +20,15 @@ namespace AmpGen double m_width; ///< width [MeV] double m_wErrPlus; ///< +ve width error [MeV] double m_wErrMinus; ///< -ve width error [MeV] - double m_Radius; ///< hadronic radius + double m_radius; ///< hadronic radius int m_Gparity; ///< G-parity - int m_Parity; ///< Parity + int m_parity; ///< Parity int m_Cparity; ///< Charge 'parity' int m_pdgID; ///< PDG id int m_Rexist; ///< likelihood of existence, baryons only int m_charge; ///< electrical charge int m_twoSpin; ///< twice the spin - std::string m_Isospin; ///< isospin + std::string m_isospin; ///< isospin std::string m_JtotalSpin; ///< total spin std::string m_name; ///< particle name std::string m_quarks; ///< quark string @@ -56,12 +56,12 @@ namespace AmpGen double radius() const; int G() const { return m_Gparity; } - int P() const { return m_Parity; } + int P() const { return m_parity; } int C() const { return m_Cparity; } int R() const { return m_Rexist; } int pdgID() const { return m_pdgID; } int twoSpin() const { return m_twoSpin ; } - std::string I() const { return m_Isospin; } + std::string I() const { return m_isospin; } std::string J() const { return m_JtotalSpin; } int charge() const { return m_charge; } std::string label() const { return m_texName; } diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index e161decdc1e..2858ee2f5cc 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -76,7 +76,7 @@ namespace AmpGen std::vector> m_polStates; EventType m_eventType; std::string m_prefix = ""; - std::vector m_psi; + std::vector m_rho; std::vector m_integIndex; std::vector>> m_matrixElements; CompiledExpression m_probExpression; diff --git a/AmpGen/Vertex.h b/AmpGen/Vertex.h index 2f2101c273a..5ea2b76fdb7 100644 --- a/AmpGen/Vertex.h +++ b/AmpGen/Vertex.h @@ -151,8 +151,8 @@ namespace AmpGen DECLARE_VERTEX( S_ff_S ); DECLARE_VERTEX( S_ff_S1 ); - DECLARE_VERTEX( V_ff_P ); - DECLARE_VERTEX( V_ff_P1 ); + DECLARE_VERTEX( V_ff_S ); + DECLARE_VERTEX( V_ff_S1 ); class Factory : public AmpGen::Factory { public: diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp index 9bf6b02aecb..6867b34bfea 100644 --- a/examples/QcGenerator.cpp +++ b/examples/QcGenerator.cpp @@ -431,11 +431,11 @@ TTree* DTEventList::tree(const std::string& name) } for( auto& evt: *this ){ bool swap = gRandom->Uniform() > 0.5; - tmp.set( evt.signal, evt.tag ); + tmp.set(evt.signal, evt.tag); if( swap ) tmp.invertParity(); - for(size_t i=0;i< m_sigType.size(); ++i) + for(size_t i=0; i != m_sigType.size(); ++i) id_sig[i] = swap ? -ids_sig[i] : ids_sig[i]; - for(size_t i=0;i< m_tagType.size(); ++i) + for(size_t i=0; i != m_tagType.size(); ++i) id_tag[i] = swap ? -ids_tag[i] : ids_tag[i]; outputTree->Fill(); } diff --git a/options/mass_width.csv b/options/mass_width.csv index 34736146064..75322a24e3c 100644 --- a/options/mass_width.csv +++ b/options/mass_width.csv @@ -409,7 +409,7 @@ 3.637E+03 ,4.0E+00,4.0E+00,1.4E+01 ,7.0E+00,7.0E+00,0 ,+,0 ,-,+, , 100441, 0, ,R,eta(c)(2S) ,cC 3.68609E+03 ,4.0E-02,4.0E-02,3.17E-01 ,9.0E-03,9.0E-03,0 ,-,1 ,-,-, , 100443, 0, ,R,psi(2S) ,cC 3.77292E+03 ,3.5E-01,3.5E-01,2.730E+01 ,1.0E+00,1.0E+00,0 ,-,1 ,-,-, , 30443, 0, ,R,psi(3770) ,cC -3.8722E+03 ,8.0E-01,8.0E-01,3.0E+00 ,2.1E+00,1.7E+00,0 ,?,1 ,?,+, ,9930443, 0, ,R,X(3872) ,cC +3.8722E+03 ,8.0E-01,8.0E-01,3.0E+00 ,2.1E+00,1.7E+00,0 ,+,1 ,+,+, ,9930443, 0, ,R,X(3872) ,cC 3.929E+03 ,5.0E+00,5.0E+00,2.90E+01 ,1.0E+01,1.0E+01,0 ,+,2 ,+,+, , 100445, 0, ,S,chi(c2)(2P) ,cC 3.943E+03 ,8.0E+00,8.0E+00,52 ,-1 ,-1 ,? ,?,? ,?,?, , , 0, ,S,X(3940) ,cC 3.943E+03 ,1.7E+01,1.7E+01,8.7E+01 ,3.4E+01,3.4E+01,? ,?,? ,?,?, , , 0, ,S,X(3945) ,cC diff --git a/src/DiracMatrices.cpp b/src/DiracMatrices.cpp index 338dacbe399..3cd7cf50935 100644 --- a/src/DiracMatrices.cpp +++ b/src/DiracMatrices.cpp @@ -35,10 +35,9 @@ extern const std::array AmpGen::Gamma ( { extern const std::array AmpGen::Sigma ( { - Tensor({0,1,1,0},{2,2}), - Tensor({Z,-I, - I,Z},{2,2}), - Tensor({1,0,0,-1},{2,2}) + Tensor({0,1,1,0} , Tensor::dim(2,2)), + Tensor({Z,-I,I,Z}, Tensor::dim(2,2)), + Tensor({1,0,0,-1}, Tensor::dim(2,2)) } ); extern const std::array AmpGen::S03 ( { @@ -54,3 +53,15 @@ extern const std::array AmpGen::S03 ( { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } , Tensor::dim(4,4) ) } ); + +extern const std::array AmpGen::SU3 ( { + Tensor({ 0, 1, 0, 1, 0, 0, 0, 0, 0}, Tensor::dim(3,3)), /// lambda1 + Tensor({ Z,-I, Z, I, Z, Z, Z, Z, Z}, Tensor::dim(3,3)), /// lambda2 + Tensor({ 1, 0, 0, 0,-1, 0, 0, 0, 0}, Tensor::dim(3,3)), /// lambda3 + Tensor({ 0, 0, 1, 0, 0, 0, 1, 0, 0}, Tensor::dim(3,3)), /// lambda4 + Tensor({ Z, Z,-I, Z, Z, Z, I, Z, Z}, Tensor::dim(3,3)), /// lambda5 + Tensor({ 0, 0, 0, 0, 0, 1, 0, 1, 0}, Tensor::dim(3,3)), /// lambda6 + Tensor({ Z, Z, Z, Z, Z,-I, Z, I, Z}, Tensor::dim(3,3)), /// lambda7 + Tensor({ 1./sqrt(3), 0., 0., 0.,1./sqrt(3.), 0., 0., 0., -2./sqrt(3.)}, Tensor::dim(3,3)) + }); + diff --git a/src/Lineshapes.cpp b/src/Lineshapes.cpp index e77940c4451..b101b615c37 100644 --- a/src/Lineshapes.cpp +++ b/src/Lineshapes.cpp @@ -123,8 +123,7 @@ Expression Lineshape::Factory::get( const std::string& lineshape, const Expressi } } -Expression Lineshape::Factory::get(const std::string& lineshape, const Expression& s, const std::vector& p, - const std::string& particleName, const unsigned int& L, +Expression Lineshape::Factory::get(const std::string& lineshape, const AmpGen::Particle& p, DebugSymbols* dbexpressions ) { size_t pos = lineshape.find( "." ); @@ -132,9 +131,9 @@ Expression Lineshape::Factory::get(const std::string& lineshape, const Expressio if ( pos == std::string::npos ) { auto it = AmpGen::Factory::get( lineshape ); if ( !it ) ERROR( "Lineshape : " << lineshape << " not found" ); - return it->get(s, p, particleName, L, "", dbexpressions ); + return it->get(p, "", dbexpressions ); } else { - return AmpGen::Factory::get( lineshape.substr( 0, pos ) )->get(s, p, particleName, L, lineshape.substr( pos + 1 ), dbexpressions ); + return AmpGen::Factory::get( lineshape.substr( 0, pos ) )->get(p, lineshape.substr( pos + 1 ), dbexpressions ); } } diff --git a/src/Lineshapes/BW.cpp b/src/Lineshapes/BW.cpp index 5f771cdc901..082e2740c00 100644 --- a/src/Lineshapes/BW.cpp +++ b/src/Lineshapes/BW.cpp @@ -6,6 +6,7 @@ #include "AmpGen/Lineshapes.h" #include "AmpGen/ParticleProperties.h" #include "AmpGen/ParticlePropertiesList.h" +#include "AmpGen/Particle.h" using namespace AmpGen; using namespace AmpGen::fcn; diff --git a/src/Lineshapes/EtaDalitz.cpp b/src/Lineshapes/EtaDalitz.cpp index f7d7a525774..b43d691f5c0 100644 --- a/src/Lineshapes/EtaDalitz.cpp +++ b/src/Lineshapes/EtaDalitz.cpp @@ -12,13 +12,14 @@ using namespace AmpGen::fcn; DEFINE_GENERIC_SHAPE( EtaDalitz ) { - WARNING("Empirical expression; eta0[EtaDalitz.NonRelBW]{pi+,pi-,pi0} with pi0 in the 3rd order."); - Tensor P( Tensor::dim(4) ); - for ( auto& ip : p ) P = P + ip; + auto pp = *p.daughter("pi+"); + auto pm = *p.daughter("pi-"); + auto p0 = *p.daughter("pi0"); + auto P = p.P(); - Expression T0 = sqrt( dot( p[0], P ) * dot( p[0], P ) / dot( P, P ) ) - sqrt( dot( p[0], p[0] ) ); - Expression T1 = sqrt( dot( p[1], P ) * dot( p[1], P ) / dot( P, P ) ) - sqrt( dot( p[1], p[1] ) ); - Expression T2 = sqrt( dot( p[2], P ) * dot( p[2], P ) / dot( P, P ) ) - sqrt( dot( p[2], p[2] ) ); + Expression T0 = dot(pp.P(), P) - p.mass() * pp.mass(); + Expression T1 = dot(pm.P(), P) - p.mass() * pm.mass(); + Expression T2 = dot(p0.P(), P) - p.mass() * p0.mass(); Expression Q = T0 + T1 + T2; Expression y = 3.0 * T2 / Q - 1.0; @@ -26,7 +27,7 @@ DEFINE_GENERIC_SHAPE( EtaDalitz ) Expression amp = Ternary( z > 0.0, sqrt(z), 1 ); if ( lineshapeModifier != "" ){ - amp = amp * Lineshape::Factory::get(lineshapeModifier, s, p, particleName, L, dbexpressions); + amp = amp * Lineshape::Factory::get(lineshapeModifier, p, dbexpressions); } return amp; } diff --git a/src/Particle.cpp b/src/Particle.cpp index 00fc6963988..8bfca42f9ea 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -195,7 +195,13 @@ void Particle::pdgLookup() << " d1 = " << m_daughters[1]->name() ); } if ( m_orbital == 0 ) m_orbital = m_minL; // define in ground state unless specified - for ( auto& d : m_daughters ) d->setTop( false ); + int charge = 0; + for ( auto& d : m_daughters ){ + d->setTop( false ); + charge += d->props()->charge(); + } + if( m_minL == 999 ) ERROR("Decay: " << m_name << " does not appear to have an allowed spin-orbit configuration"); + if( m_daughters.size() != 0 && m_props->charge() != charge ) ERROR("Decay: " << m_name << " does not conserve (electric) charge"); } Tensor Particle::P() const @@ -231,6 +237,22 @@ Tensor Particle::Q() const std::shared_ptr Particle::daughter( const size_t& index ) { return ( m_daughters[index] ); } std::shared_ptr Particle::daughter( const size_t& index ) const { return m_daughters[index]; } +std::shared_ptr Particle::daughter( const std::string& name, const int& maxDepth ) const +{ + if( maxDepth == -1 ) + { + auto fs = getFinalStateParticles(); + for( auto& f : fs ) if( f->name() == name ) return f; + ERROR("Particle: " << name << " not found amongst decay products!"); + } + else { + for( auto& d : m_daughters ) if( d->name() == name ) return d; + ERROR("Particle: " << name << " not found amongst decay products!"); + } + return std::shared_ptr(); +} + + std::string Particle::orbitalString() const { std::string orbital_part; @@ -321,14 +343,11 @@ Expression Particle::propagator( DebugSymbols* db ) const Expression prop = 1; if ( m_daughters.size() == 2 ) prop = Lineshape::Factory::get(m_lineshape, s, daughter(0)->massSq(), daughter(1)->massSq(), m_name, m_orbital, db); - else if ( m_daughters.size() == 3 ) - prop = Lineshape::Factory::get(m_lineshape == "BW" ? "SBW" : m_lineshape, massSq(), {daughter(0)->P(), daughter(1)->P(), daughter(2)->P()}, m_name, m_orbital, db ); + else if ( m_daughters.size() >= 3 ) + prop = Lineshape::Factory::get(m_lineshape == "BW" ? "SBW" : m_lineshape, *this, db ); else if ( m_daughters.size() == 1 && m_lineshape != "BW" && m_lineshape != "FormFactor" ) { - std::vector p_vector; - auto fs = getFinalStateParticles(true); - for( auto& d : fs ) p_vector.emplace_back( d->P() ); - prop = Lineshape::Factory::get(m_lineshape, massSq(), p_vector, m_name, m_orbital, db ); + prop = Lineshape::Factory::get(m_lineshape, *this, db ); } total = total * make_cse(prop); for(auto& d : m_daughters) total = total*make_cse(d->propagator(db)); @@ -533,23 +552,6 @@ Tensor Particle::externalSpinTensor(const int& polState, DebugSymbols* db ) cons return Tensor( std::vector( {1.} ), Tensor::dim(0) ); } -bool Particle::checkExists() const -{ - bool success = true; - if ( m_daughters.size() == 2 ) { - success &= Vertex::Factory::isVertex( vertexName() ); - if ( !success ) { - ERROR( uniqueString() ); - ERROR( "Spin configuration not found J = " - << spin() << " L = " << m_orbital << " l' = " << m_spinConfigurationNumber - << " s1 = " << m_daughters[0]->spin() << " s2 = " << m_daughters[1]->spin() ); - } - success &= daughter(0)->checkExists() & daughter(1)->checkExists(); - } - if ( success == false ) ERROR( uniqueString() << " is not described in IVertex" ); - return success; -} - std::pair Particle::orbitalRange( const bool& conserveParity ) const { if( m_daughters.size() == 0 ) return {0, 0}; diff --git a/src/ParticleProperties.cpp b/src/ParticleProperties.cpp index ae80229b683..0be1b6d97ec 100644 --- a/src/ParticleProperties.cpp +++ b/src/ParticleProperties.cpp @@ -56,10 +56,10 @@ ParticleProperties::ParticleProperties( const std::string& pdg_string ) : m_netQ m_pdgID = lexical_cast( s[12], status ); m_Rexist = lexical_cast( s[14], status ); m_Gparity = chargeFromString( s[7], status ); - m_Parity = chargeFromString( s[9], status ); + m_parity = chargeFromString( s[9], status ); m_Cparity = chargeFromString( s[10], status ); m_charge = chargeFromString( s[13], status ); - m_Isospin = s[6]; + m_isospin = s[6]; m_JtotalSpin = s[8]; m_status = s[15][0]; m_name = s[16]; @@ -88,7 +88,7 @@ void ParticleProperties::setRadius() abs(pdgID()) == 411 || abs(pdgID()) == 431 || abs(pdgID()) == 4122 ); - m_Radius = isCharm ? defaultCharmRadius : defaultRadius; + m_radius = isCharm ? defaultCharmRadius : defaultRadius; } void ParticleProperties::antiQuarks() @@ -112,6 +112,7 @@ void ParticleProperties::antiCharge() { swapChars( m_chargeString, '+', '-'); m_charge *= -1; + if( isFermion() ) m_parity *= -1; } bool ParticleProperties::hasDistinctAnti() const { return !( m_Aformat == ' ' ); } @@ -141,7 +142,7 @@ std::string ParticleProperties::name() const fullName += m_chargeString; return fullName; } -double ParticleProperties::radius() const { return m_Radius; } +double ParticleProperties::radius() const { return m_radius; } bool ParticleProperties::isNonResonant() const { diff --git a/src/ParticlePropertiesList.cpp b/src/ParticlePropertiesList.cpp index 9745d94f59d..88661fc57bb 100644 --- a/src/ParticlePropertiesList.cpp +++ b/src/ParticlePropertiesList.cpp @@ -98,7 +98,7 @@ bool ParticlePropertiesList::readFile( const std::string& name ) DEBUG( "File not found: " << name ); return false; } - DEBUG( "Reading file: " << name ); + INFO( "Reading file: " << name ); processFile( name, [this]( auto& line ) { if ( line[0] == '*' ) return; ParticleProperties P( line ); diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 99e0530ed63..8b0ecc5bd54 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -43,23 +43,22 @@ PolarisedSum::PolarisedSum( const EventType& type, bool autoCompile = NamedParameter( "PolarisedSum::AutoCompile",true ); std::string objCache = NamedParameter("PolarisedSum::ObjectCache","" ); m_verbosity = NamedParameter( "PolarisedSum::Verbosity" ,0 ); - m_rules = AmplitudeRules(mps); - auto proto_amplitudes = m_rules.getMatchingRules( type, prefix); - auto production_polarisations = polarisations( type.mother() ); - std::vector> allStates; - for(auto& pol : production_polarisations ) allStates.push_back({pol}); - for(size_t i = 0 ; i < type.size(); ++i ) allStates = polarisationOuterProduct( allStates, polarisations( type[i] ) ); + m_rules = AmplitudeRules(mps); + auto protoAmps = m_rules.getMatchingRules( type, prefix); + auto prodPols = polarisations( type.mother() ); + for(auto& pol : prodPols ) m_polStates.push_back({pol}); + for(size_t i = 0 ; i < type.size(); ++i ) m_polStates = polarisationOuterProduct(m_polStates, polarisations( type[i] ) ); auto set_polarisation_state = []( auto& matrix_element, auto& polState ){ auto fs = matrix_element.first.getFinalStateParticles(); matrix_element.first.setPolarisationState(polState[0]); for(size_t i = 0 ; i < fs.size(); ++i ) fs[i]->setPolarisationState( polState[i+1] ); }; - for( auto& m : proto_amplitudes ) INFO( m.first.uniqueString() ); - for( auto& matrix_element : proto_amplitudes ){ - Tensor thisExpression( std::vector({allStates.size()}) ); + for( auto& m : protoAmps ) INFO( m.first.uniqueString() ); + for( auto& matrix_element : protoAmps ){ + Tensor thisExpression( Tensor::dim(m_polStates.size()) ); int i = 0 ; DebugSymbols syms; - for( auto& polState : allStates ){ + for( auto& polState : m_polStates ){ set_polarisation_state( matrix_element, polState ); thisExpression[i++] = make_cse( matrix_element.first.getExpression(&syms) ); } @@ -68,21 +67,16 @@ PolarisedSum::PolarisedSum( const EventType& type, matrix_element.first.decayDescriptor(), type.getEventFormat(), debug ? syms : DebugSymbols() ,&mps ); m_matrixElements.emplace_back(matrix_element.first, matrix_element.second, expression ); - } - for( auto& polState : allStates){ - for( auto& matrix_element : proto_amplitudes ){ - set_polarisation_state( matrix_element, polState ); - } } - m_polStates = allStates; if(autoCompile){ ThreadPool tp(8); - for( auto& thing : m_matrixElements ) - tp.enqueue( [&]{ CompilerWrapper().compile( thing.pdf, objCache ) ;} ); + for( auto& thing : m_matrixElements ) tp.enqueue([&]{ CompilerWrapper().compile(thing.pdf, objCache);}); } - if( mps.find("Px") == nullptr ) WARNING("Polarisation parameters not defined, defaulting to (0,0,0)"); - m_pVector = {mps.addOrGet("Px",2,0,0), mps.addOrGet("Py",2,0,0), mps.addOrGet("Pz",2,0,0)}; auto d = m_eventType.dim(); + auto p = [&mps](const std::string& name){ return mps.addOrGet(name,2,0,0); }; + if( d.first == 1 ) m_pVector = {}; + else if( d.first == 2 ) m_pVector = {p("Px"), p("Py"), p("Pz")}; + else if( d.first == 3 ) m_pVector = {p("Px"), p("Py"), p("Pz"), p("Tyy"), p("Tzz"), p("Txy"), p("Txz"), p("Tyz")}; size_t normSize = d.second * d.first * d.first; for(size_t i=0; i < normSize; ++i){ m_norms.emplace_back( m_matrixElements.size(), m_matrixElements.size() ); @@ -92,12 +86,15 @@ PolarisedSum::PolarisedSum( const EventType& type, std::vector PolarisedSum::polarisations( const std::string& name ) const { auto props = *ParticlePropertiesList::get( name ); - std::vector rt( props.twoSpin() + 1 ); - if( props.isFermion() ) return {1,-1}; if( props.twoSpin() == 0 ) return {0}; - if( props.twoSpin() == 2 ) - return (name == "gamma0") ? std::vector({-1,1}) : std::vector({-1,0,1}) ; - else return {0}; + if( props.twoSpin() == 1 ) return {1,-1}; + if( name == "gamma0" && props.twoSpin() == 2 ) return {1,-1}; + if( name != "gamma0" && props.twoSpin() == 2 ) return {1,0,-1}; + + else { + WARNING("Particle with spin: " << props.twoSpin() << "/2" << " not implemented in initial/final state"); + return {0}; + } } std::vector> PolarisedSum::polarisationOuterProduct(const std::vector>& A, const std::vector& B ) const @@ -112,6 +109,35 @@ std::vector> PolarisedSum::polarisationOuterProduct(const std:: return rt; } +std::vector densityMatrix(const size_t& dim, const std::vector& pv ) +{ + double px = pv[0]; + double py = pv[1]; + double pz = pv[2]; + if( dim == 1 ) return {1.}; + if( dim == 2 ) return {1+pz , px+1i*py, + px-1i*py, 1-pz }; + if( dim == 3 ){ + double Tyy = pv[3]; + double Tzz = pv[4]; + double Txy = pv[5]; + double Txz = pv[6]; + double Tyz = pv[7]; + return {1 + 1.5*pz + sqrt(1.5)*Tzz , sqrt(0.375)*(px+1i*py) + sqrt(3.)*(Txz+1i*Tyz), -sqrt(1.5)*( Tzz + 2.*Tyy - 2.*1i*Txy), + sqrt(0.375)*(px-1i*py) + sqrt(3)*(Txz-1i*Tyz), 1 - sqrt(6.)*Tzz , sqrt(0.375)*(px+1i*py) - sqrt(3.)*(Txz+1i*Tyz) , + -sqrt(1.500)*( Tzz + 2.*Tyy + 2.*1i*Txy) , sqrt(0.375)*(px-1i*py) - sqrt(3)*(Txz-1i*Tyz) , 1. - 1.5*pz + sqrt(1.5)*Tzz }; + } + ERROR("Density matrices not implemented for state with size="< convertProxies(const std::vector& proxyVector, const std::function& transform) +{ + std::vector rt; + std::transform(proxyVector.begin(), proxyVector.end(), std::back_inserter(rt), transform ); + return rt; +} + std::vector>> PolarisedSum::matrixElements() const { return m_matrixElements; @@ -126,10 +152,8 @@ void PolarisedSum::prepare() size_t nChanges = 0; ProfileClock tEval; size_t size_of = size() / m_matrixElements.size(); - if( m_events != nullptr ) m_events->reserveCache( size() ); if( m_integrator.isReady() ) m_integrator.events().reserveCache( size() ); - for( size_t i = 0; i < m_matrixElements.size(); ++i ){ ProfileClock tMEval; auto& t = m_matrixElements[i]; @@ -147,14 +171,7 @@ void PolarisedSum::prepare() m_weight = m_weightParam == nullptr ? 1 : m_weightParam->mean(); tEval.stop(); ProfileClock tIntegral; - if( m_eventType.dim().first == 2 ){ - double px = m_pVector[0]; - double py = m_pVector[1]; - double pz = m_pVector[2]; - m_psi = {1+pz , px+1i*py, - px-1i*py, 1-pz }; - } - else m_psi = {1}; + m_rho = densityMatrix(m_eventType.dim().first, m_pVector); if( m_integrator.isReady() ) { if(nChanges != 0) calculateNorms(hasChanged); @@ -169,9 +186,7 @@ void PolarisedSum::prepare() } tIntegral.stop(); if(m_verbosity && nChanges != 0) - INFO("Time to evaluate = " << tEval << " ms; " - << "norm = " << tIntegral << " ms; " - << "pdfs = " << nChanges); + INFO("Time to evaluate = " << tEval << " ms; " << "norm = " << tIntegral << " ms; " << "pdfs = " << nChanges); m_nCalls++; } @@ -211,9 +226,8 @@ void PolarisedSum::reset( const bool& flag ){ m_nCalls = 0 ; } void PolarisedSum::build_probunnormalised() { - auto prob = probExpression(transitionMatrix(), {Parameter("Px"), Parameter("Py"), Parameter("Pz")}); - m_probExpression = CompiledExpression( - prob, "prob_unnormalised", std::map(), {}, m_mps ); + auto prob = probExpression(transitionMatrix(), convertProxies(m_pVector,[](auto& p){ return Parameter(p->name());} ) ); + m_probExpression = CompiledExpression(prob, "prob_unnormalised", std::map(), {}, m_mps); CompilerWrapper().compile(m_probExpression); m_probExpression.prepare(); } @@ -222,7 +236,7 @@ Tensor PolarisedSum::transitionMatrix() { auto dim = m_eventType.dim(); auto size = dim.first * dim.second ; - std::vector expressions( size, 0); + std::vector expressions(size, 0); for( auto& me : m_matrixElements ){ auto coupling = me.coupling.to_expression() ; auto cacheIndex = m_events->getCacheIndex(me.pdf); @@ -258,7 +272,7 @@ complex_t PolarisedSum::norm(const size_t& i, const size_t& j, Integrator<18>* i auto psiIndex = (x-f) / s2; auto m2 = psiIndex % s1; auto m1 = (psiIndex-m2)/s1; - total += m_psi[psiIndex] * m_norms[x].get(i, j, integ, ai+m1*s2+f, aj+m2*s2+f); + total += m_rho[psiIndex] * m_norms[x].get(i, j, integ, ai+m1*s2+f, aj+m2*s2+f); } return total; } @@ -311,23 +325,18 @@ void PolarisedSum::generateSourceCode(const std::string& fname, const double& no } Tensor T_matrix( expressions, {dim.first,dim.second} ); T_matrix.st(); - auto amplitude = probExpression(T_matrix, {Constant(double(m_pVector[0])), - Constant(double(m_pVector[1])), - Constant(double(m_pVector[2]))}); - - auto amplitude_extPol = probExpression(T_matrix, {Parameter("x2",0,true), - Parameter("x3",0,true), - Parameter("x4",0,true)}); + auto amp = probExpression(T_matrix, convertProxies(m_pVector, [](auto& proxy) -> Expression{ return double(proxy);} )); + auto amp_extPol = probExpression(T_matrix, {Parameter("x2",0,true), Parameter("x3",0,true), Parameter("x4",0,true)}); stream << CompiledExpression( amplitude / normalisation, "FCN",{},{}, m_mps ) << std::endl ; + const int&>( amp / normalisation, "FCN",{},{}, m_mps ) << std::endl ; stream << CompiledExpression( amplitude_extPol / normalisation, "FCN_extPol",{},{},m_mps ) << std::endl; + const double&>( amp_extPol / normalisation, "FCN_extPol",{},{},m_mps ) << std::endl; stream.close(); } @@ -338,7 +347,7 @@ Expression PolarisedSum::probExpression(const Tensor& T_matrix, const std::vecto Tensor TT = T_matrix(a,b) * T_conj(c,b); size_t it = T_matrix.dims()[0]; Tensor rho = Identity(it); - if(it == 2) rho = rho + Sigma[0] * p[0] + Sigma[1] * p[1] + Sigma[2]*p[2]; + if(it == 2) rho = rho + Sigma[0] * p[0] + Sigma[1] * p[1] + Sigma[2]*p[2]; Expression rt = rho(a,b) * TT(b,a); return Real(rt); } diff --git a/src/QuarkContent.cpp b/src/QuarkContent.cpp index ae38efea63b..6ced6629638 100644 --- a/src/QuarkContent.cpp +++ b/src/QuarkContent.cpp @@ -15,7 +15,7 @@ std::map QuarkState::gPositions; QuarkState::QuarkState() { - for ( auto& quark : m_quarks ) quark = 0; + std::fill( m_quarks.begin(), m_quarks.end(), 0 ); initPositions(); } @@ -38,7 +38,8 @@ bool QuarkState::initPositions() void QuarkState::antiThis() { - for ( auto& quark : m_quarks ) quark *= -1; + std::transform( m_quarks.begin(), m_quarks.end(), m_quarks.begin(), [](const auto& quark){ return (-1)*quark ; } ); +// for ( auto& quark : m_quarks ) quark *= -1; } char QuarkState::nameFromPosition( int i ) const diff --git a/src/Vertex.cpp b/src/Vertex.cpp index 5c1faf158df..11a8557bf4b 100644 --- a/src/Vertex.cpp +++ b/src/Vertex.cpp @@ -389,7 +389,6 @@ DEFINE_VERTEX( S_ff_S ) { return Bar(V2)(a) * V1(a); } DEFINE_VERTEX( S_ff_S1 ){ return Bar(V2)(a) * Gamma[4](a,b) * V1(b); } +DEFINE_VERTEX( V_ff_S ) { return Bar(V2)(a) * Gamma4Vec()(mu,a,b) * V1(b); } -DEFINE_VERTEX( V_ff_P ) { return Bar(V2)(a) * Gamma4Vec()(mu,a,b) * V1(b); } - -DEFINE_VERTEX( V_ff_P1 ){ return Bar(V2)(a) * Gamma[4](a,b) * Gamma4Vec()(mu,b,c) * V1(c); } +DEFINE_VERTEX( V_ff_S1 ){ return Bar(V2)(a) * Gamma[4](a,b) * Gamma4Vec()(mu,b,c) * V1(c); } diff --git a/src/Wigner.cpp b/src/Wigner.cpp index 0588a4b44ef..ddca29c3711 100644 --- a/src/Wigner.cpp +++ b/src/Wigner.cpp @@ -30,7 +30,7 @@ double fact( const double& z ) return f; } -double nCr_( const int& n, const int& r ){ +double binomialCoefficient( const int& n, const int& r ){ double z=1; for( int f=1; f <= r ; ++f ) z *= double(n+1-f)/double(f); return z; @@ -39,7 +39,7 @@ double nCr_( const int& n, const int& r ){ Expression expandedBinomial( const Expression& x, const unsigned int& n ) { Expression sum; - for( unsigned int k = 0 ; k <= n ; ++k ) sum = sum + nCr_(n,k) * fcn::fpow(x,k); + for( unsigned int k = 0 ; k <= n ; ++k ) sum = sum + binomialCoefficient(n,k) * fcn::fpow(x,k); return sum; } @@ -80,10 +80,8 @@ double AmpGen::CG( if( m1+m2!=M ) return 0; double f1 = (2*J+1)*fact(J+j1-j2)*fact(J-j1+j2)*fact(j1+j2-J) ; double f2 = fact(j1+m1)*fact(j1-m1)*fact(j2+m2)*fact(j2-m2)*fact(J+M)*fact(J-M); - double norm = f1 * f2 / fact(J+j1+j2+1) ; double sum = 0; - for( int nu=0; nu <= j1+j2-J ; ++nu){ double arg1 = j1+j2-J-double(nu); double arg2 = j1 -m1-double(nu); From acfa0b3390846d85817880b71dd39275a7306ddc Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 8 Jul 2019 15:41:48 +0200 Subject: [PATCH 079/250] fix PolarisedSum::densityMatrix for scalar case, neaten formatting in DiracMatrices.cpp --- src/DiracMatrices.cpp | 72 +++++++++++++------------------------------ src/PolarisedSum.cpp | 2 +- 2 files changed, 23 insertions(+), 51 deletions(-) diff --git a/src/DiracMatrices.cpp b/src/DiracMatrices.cpp index 3cd7cf50935..938c41de246 100644 --- a/src/DiracMatrices.cpp +++ b/src/DiracMatrices.cpp @@ -11,57 +11,29 @@ using namespace AmpGen; extern const AmpGen::Expression AmpGen::I = Constant(0, 1); extern const AmpGen::Expression AmpGen::Z = Constant(0); -extern const std::array AmpGen::Gamma ( { - Tensor ({ 0, 0, 0, 1, - 0, 0, 1, 0, - 0,-1, 0, 0, - -1, 0, 0, 0} , {4, 4}), - Tensor ({ Z, Z, Z,-I, - Z, Z, I, Z, - Z, I, Z, Z, - -I, Z, Z, Z} , {4, 4}), - Tensor ({ 0, 0, 1, 0, - 0, 0, 0,-1, - -1, 0, 0, 0, - 0, 1, 0, 0} , {4, 4}), - Tensor ({ 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0,-1, 0, - 0, 0, 0,-1} , {4, 4}), - Tensor ({ 0, 0, 1, 0, - 0, 0, 0, 1, - 1, 0, 0, 0, - 0, 1, 0, 0} , {4, 4})} ); - -extern const std::array AmpGen::Sigma ( - { - Tensor({0,1,1,0} , Tensor::dim(2,2)), - Tensor({Z,-I,I,Z}, Tensor::dim(2,2)), - Tensor({1,0,0,-1}, Tensor::dim(2,2)) - } ); +extern const std::array AmpGen::Gamma( { + Tensor({ 0, 0, 0, 1, 0, 0, 1, 0, 0,-1, 0, 0,-1, 0, 0, 0}, Tensor::dim(4,4)), + Tensor({ Z, Z, Z,-I, Z, Z, I, Z, Z, I, Z, Z,-I, Z, Z, Z}, Tensor::dim(4,4)), + Tensor({ 0, 0, 1, 0, 0, 0, 0,-1,-1, 0, 0, 0, 0, 1, 0, 0}, Tensor::dim(4,4)), + Tensor({ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0,-1, 0, 0, 0, 0,-1}, Tensor::dim(4,4)), + Tensor({ 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0}, Tensor::dim(4,4))} ); + +extern const std::array AmpGen::Sigma( { + Tensor({ 0, 1, 1, 0}, Tensor::dim(2,2)), + Tensor({ Z,-I, I, Z}, Tensor::dim(2,2)), + Tensor({ 1, 0, 0,-1}, Tensor::dim(2,2))} ); extern const std::array AmpGen::S03 ( { - Tensor ({ 0, 0, 0, 0, - 0, 0,-1, 0, - 0, 1, 0, 0, - 0, 0, 0, 0 } , Tensor::dim(4,4) ), - Tensor ({ 0, 0, 1, 0, - 0, 0, 0, 0, - -1, 0, 0, 0, - 0, 0, 0, 0 } , Tensor::dim(4,4) ), - Tensor ({ 0,-1, 0, 0, - 1, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 } , Tensor::dim(4,4) ) } ); + Tensor({ 0, 0, 0, 0, 0, 0,-1, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, Tensor::dim(4,4) ), + Tensor({ 0, 0, 1, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0 }, Tensor::dim(4,4) ), + Tensor({ 0,-1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, Tensor::dim(4,4) ) } ); extern const std::array AmpGen::SU3 ( { - Tensor({ 0, 1, 0, 1, 0, 0, 0, 0, 0}, Tensor::dim(3,3)), /// lambda1 - Tensor({ Z,-I, Z, I, Z, Z, Z, Z, Z}, Tensor::dim(3,3)), /// lambda2 - Tensor({ 1, 0, 0, 0,-1, 0, 0, 0, 0}, Tensor::dim(3,3)), /// lambda3 - Tensor({ 0, 0, 1, 0, 0, 0, 1, 0, 0}, Tensor::dim(3,3)), /// lambda4 - Tensor({ Z, Z,-I, Z, Z, Z, I, Z, Z}, Tensor::dim(3,3)), /// lambda5 - Tensor({ 0, 0, 0, 0, 0, 1, 0, 1, 0}, Tensor::dim(3,3)), /// lambda6 - Tensor({ Z, Z, Z, Z, Z,-I, Z, I, Z}, Tensor::dim(3,3)), /// lambda7 - Tensor({ 1./sqrt(3), 0., 0., 0.,1./sqrt(3.), 0., 0., 0., -2./sqrt(3.)}, Tensor::dim(3,3)) - }); - + Tensor({ 0, 1, 0, 1, 0, 0, 0, 0, 0}, Tensor::dim(3,3)), + Tensor({ Z,-I, Z, I, Z, Z, Z, Z, Z}, Tensor::dim(3,3)), + Tensor({ 1, 0, 0, 0,-1, 0, 0, 0, 0}, Tensor::dim(3,3)), + Tensor({ 0, 0, 1, 0, 0, 0, 1, 0, 0}, Tensor::dim(3,3)), + Tensor({ Z, Z,-I, Z, Z, Z, I, Z, Z}, Tensor::dim(3,3)), + Tensor({ 0, 0, 0, 0, 0, 1, 0, 1, 0}, Tensor::dim(3,3)), + Tensor({ Z, Z, Z, Z, Z,-I, Z, I, Z}, Tensor::dim(3,3)), + Tensor({ 1./sqrt(3), 0., 0., 0.,1./sqrt(3.), 0., 0., 0., -2./sqrt(3.)}, Tensor::dim(3,3)) }); diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 8b0ecc5bd54..569d3ccad9c 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -111,10 +111,10 @@ std::vector> PolarisedSum::polarisationOuterProduct(const std:: std::vector densityMatrix(const size_t& dim, const std::vector& pv ) { + if( dim == 1 ) return {1.}; double px = pv[0]; double py = pv[1]; double pz = pv[2]; - if( dim == 1 ) return {1.}; if( dim == 2 ) return {1+pz , px+1i*py, px-1i*py, 1-pz }; if( dim == 3 ){ From f10eb29c9a9daba70f4178ff19a166fc0181e1dd Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 8 Jul 2019 23:42:00 +0200 Subject: [PATCH 080/250] Fix unit tests under boost 1.70.0 --- Standalone.cmake | 14 ++++++------- test/test_ExpressionParser.cpp | 38 +++++++++++++++++++--------------- test/test_utilities.cpp | 14 +++++++++---- 3 files changed, 38 insertions(+), 28 deletions(-) diff --git a/Standalone.cmake b/Standalone.cmake index f78be327551..1bf5289715a 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -126,14 +126,14 @@ target_compile_options(AmpGen -Wno-unused-parameter -Wno-unknown-pragmas -Wnon-virtual-dtor - -Woverloaded-virtual + -Wno-overloaded-virtual -march=native $<$:-Ofast>) if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -lstdc++") else() - target_compile_options(AmpGen PUBLIC -Wsuggest-override) + target_compile_options(AmpGen PUBLIC -Wno-suggest-override) endif() file(GLOB_RECURSE applications apps/*.cpp ) @@ -163,12 +163,12 @@ foreach(file ${options_files}) endforeach() enable_testing() +set(Boost_NO_BOOST_CMAKE ON) + find_package(Boost 1.67.0 COMPONENTS unit_test_framework) if ( Boost_FOUND ) include_directories (${Boost_INCLUDE_DIRS}) - file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cpp) - foreach(testSrc ${TEST_SRCS}) get_filename_component(testName ${testSrc} NAME_WE) add_executable(${testName} ${testSrc}) @@ -179,10 +179,10 @@ if ( Boost_FOUND ) RUNTIME_OUTPUT_DIRECTORY "${CMAKE_TEST_OUTPUT_DIRECTORY}" EXECUTABLE_OUTPUT_DIRECTORY "${CMAKE_TEST_OUTPUT_DIRECTORY}" ) - target_link_libraries(${testName} ${Boost_LIBRARIES} AmpGen) - add_test(NAME ${testName} WORKING_DIRECTORY ${CMAKE_TEST_OUTPUT_DIRECTORY} COMMAND ${CMAKE_TEST_OUTPUT_DIRECTORY}/${testName} ) + target_link_libraries(${testName} PUBLIC ${Boost_LIBRARIES} AmpGen) + add_test(NAME ${testName} WORKING_DIRECTORY ${CMAKE_TEST_OUTPUT_DIRECTORY} COMMAND ${CMAKE_TEST_OUTPUT_DIRECTORY}/${testName} ) endforeach(testSrc) else() - message( WARNING "Warning: Boost (version >=1.67.0) required to build unit tests\n") + message( WARNING "Warning: Boost (version >= 1.67.0) required to build unit tests\n") endif() diff --git a/test/test_ExpressionParser.cpp b/test/test_ExpressionParser.cpp index 29f36b23d84..de05c5a99a5 100644 --- a/test/test_ExpressionParser.cpp +++ b/test/test_ExpressionParser.cpp @@ -9,8 +9,19 @@ namespace utf = boost::unit_test; #include "AmpGen/MinuitParameterSet.h" using namespace AmpGen; + +BOOST_AUTO_TEST_CASE( simple_numericalExpressions ){ + auto test = [](const std::string& expr) -> double { return std::real( ExpressionParser::parse(expr)() ); }; + BOOST_CHECK( test("1 + 2 * 3" ) == 1 + 2 * 3 ); + BOOST_CHECK( test("4 + 2 " ) == 6 ); + BOOST_CHECK( test("3 * 6 - 7 + 2 " ) == 3 * 6 - 7 + 2 ); + BOOST_CHECK( test("6 * 2 + ( 5 - 3 ) * 3 - 8 " ) == 6 * 2 + ( 5 - 3)*3 -8 ); + BOOST_CHECK( test("( 3 + 4 ) + 7 * 2 - 1 - 9 " ) == 3 + 4 + 7 * 2 - 1 - 9); + BOOST_CHECK( test("5 - 2 + 4 * ( 8 - ( 5 + 1 ) ) + 9 " ) == 5 - 2 + 4 *( 8 - (5+1)) +9 ); + BOOST_CHECK( test("( 8 - 1 + 3 ) * 6 - ( ( 3 + 7 ) * 2 )" ) == (8-1+3)*6 - ((3+7)*2) ); +} -BOOST_AUTO_TEST_CASE( test_ExpressionParser ) { +BOOST_AUTO_TEST_CASE( parametericExpressions ) { double a = 1.0; double b = 0.5; @@ -18,13 +29,12 @@ BOOST_AUTO_TEST_CASE( test_ExpressionParser ) { double d = 0.2; double f = 3.13; - MinuitParameterSet mps( { - new MinuitParameter("a",MinuitParameter::Flag::Float, a,0. ) - , new MinuitParameter("b",MinuitParameter::Flag::Float, b,0. ) - , new MinuitParameter("c",MinuitParameter::Flag::Float, c, 0. ) - , new MinuitParameter("d",MinuitParameter::Flag::Float, d, 0. ) - , new MinuitParameter("f",MinuitParameter::Flag::Float, f, 0. ) + new MinuitParameter("a", MinuitParameter::Flag::Float, a, 0.) + , new MinuitParameter("b", MinuitParameter::Flag::Float, b, 0.) + , new MinuitParameter("c", MinuitParameter::Flag::Float, c, 0.) + , new MinuitParameter("d", MinuitParameter::Flag::Float, d, 0.) + , new MinuitParameter("f", MinuitParameter::Flag::Float, f, 0.) }); double pi = M_PI; @@ -57,14 +67,8 @@ BOOST_AUTO_TEST_CASE( test_ExpressionParser ) { BOOST_CHECK( test("(b+a/b) * (a-b/a)") == (b+a/b) * (a-b/a) ); BOOST_CHECK( test("(0.1*a+1)*a+1.1-sin(a)-log(a)/a*3/4") == (0.1*a+1)*a+1.1-sin(a)-log(a)/a*3/4 ); BOOST_CHECK( test("sin(2 * a) + cos(pi / b)") == sin(2 * a) + cos(pi / b) ); - BOOST_CHECK( test("a - ( b + c ) " ) == a - ( b + c ) ); - BOOST_CHECK( test("a - b + c - d / b + f - a " ) == a - b + c - d / b + f -a ); - BOOST_CHECK( test("1 + 2 * 3" ) == 1 + 2 * 3 ); - BOOST_CHECK( test("4 + 2 " ) == 6 ); - BOOST_CHECK( test("3 * 6 - 7 + 2 " ) == 3 * 6 - 7 + 2 ); - BOOST_CHECK( test("6 * 2 + ( 5 - 3 ) * 3 - 8 " ) == 6 * 2 + ( 5 - 3)*3 -8 ); - BOOST_CHECK( test("( 3 + 4 ) + 7 * 2 - 1 - 9 " ) == 3 + 4 + 7 * 2 - 1 - 9); - BOOST_CHECK( test("5 - 2 + 4 * ( 8 - ( 5 + 1 ) ) + 9 " ) == 5 - 2 + 4 *( 8 - (5+1)) +9 ); - BOOST_CHECK( test("( 8 - 1 + 3 ) * 6 - ( ( 3 + 7 ) * 2 )" ) == (8-1+3)*6 - ((3+7)*2) ); - + BOOST_CHECK( test("a - ( b + c ) " ) == a - ( b + c ) ); + BOOST_CHECK( test("a - b + c - d / b + f - a " ) == a - b + c - d / b + f -a ); } + + diff --git a/test/test_utilities.cpp b/test/test_utilities.cpp index c52e2bcd565..0525d029c48 100644 --- a/test/test_utilities.cpp +++ b/test/test_utilities.cpp @@ -1,17 +1,23 @@ #define BOOST_TEST_DYN_LINK -#define BOOST_TEST_MODULE "ArgumentPack" - +#define BOOST_TEST_MODULE "Utilities" #include namespace utf = boost::unit_test; #include "AmpGen/Utilities.h" - BOOST_AUTO_TEST_CASE( test_swap_char ) { std::string test = "hello, world"; AmpGen::swapChars( test, 'h', 'w' ); - BOOST_CHECK( test == "wello, horld"); + BOOST_TEST( test == "wello, horld"); } +BOOST_AUTO_TEST_CASE( test_split ) +{ + std::string test = "hello world tokens"; + auto tokens = AmpGen::split(test,' '); + BOOST_TEST(tokens[0] == "hello"); + BOOST_TEST(tokens[1] == "world"); + BOOST_TEST(tokens[2] == "tokens"); +} From b97e16a66452844ed496aa8613732e2802ec0239 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 8 Jul 2019 23:45:41 +0200 Subject: [PATCH 081/250] Added some debugging for production polarisation --- AmpGen/CompiledExpression.h | 6 ++--- AmpGen/PolarisedSum.h | 3 ++- apps/Debugger.cpp | 2 +- src/CoherentSum.cpp | 4 +-- src/PolarisedSum.cpp | 52 ++++++++++++++++++++++++++++++------ src/ThreeBodyCalculators.cpp | 2 +- 6 files changed, 53 insertions(+), 16 deletions(-) diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index 1deff2173d1..326fe08b919 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -27,7 +27,7 @@ namespace AmpGen { private: - DynamicFCN m_fcn; + DynamicFCN m_fcn; DynamicFCN>(ARGS...)> m_fdb; std::vector m_externals = {}; bool m_hasExternalsChanged = {false}; @@ -148,8 +148,8 @@ namespace AmpGen { return m_fcn( args... ); } - - void debug( const double* event ) const + template < class T> + void debug( const T* event ) const { if ( !m_fcn.isLinked() ) { FATAL( "Function " << name() << " not linked" ); diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index 2858ee2f5cc..be04a85779e 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -48,7 +48,7 @@ namespace AmpGen void calculateNorms(const std::vector& hasChanged); void generateSourceCode( const std::string& fname, const double& normalisation = 1, bool add_mt = false ); void build_probunnormalised(); - Expression probExpression( const Tensor& T_matrix, const std::vector& p ) const; + Expression probExpression( const Tensor& T_matrix, const std::vector& p, DebugSymbols* = nullptr ) const; size_t size() const ; real_t norm() const; complex_t norm(const size_t& i, const size_t& j, Integrator<18>* integ = nullptr ); @@ -71,6 +71,7 @@ namespace AmpGen double m_weight = {1}; std::vector m_pVector = {}; bool m_verbosity = {0}; + bool m_debug = {0}; Integrator<18> m_integrator; std::vector m_norms; std::vector> m_polStates; diff --git a/apps/Debugger.cpp b/apps/Debugger.cpp index b2b7dbefc01..5bf0d9bb58b 100644 --- a/apps/Debugger.cpp +++ b/apps/Debugger.cpp @@ -87,7 +87,7 @@ template void print( const Event& event, const MatrixElem for ( auto& term : terms ) { INFO( "--> " << term.first->name() << " = (" << term.first->mean() * cos( term.second->mean() ) << " + i " << term.first->mean() * sin( term.second->mean() ) << ")" ); } - mE.pdf.debug( event ); + mE.pdf.debug( event.address() ); } } } diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 2c962862bd8..8dfb4c4c88e 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -122,11 +122,11 @@ void CoherentSum::debug( const Event& evt, const std::string& nameMustContain ) INFO( std::setw(70) << pdf.decayTree.uniqueString() << " A = [ " << std::real(A) << " " << std::imag(A) << " ] g = [ "<< std::real(pdf.coupling()) << " " << std::imag(pdf.coupling()) << " ]" ); - if( m_dbThis ) pdf.pdf.debug( evt ); + if( m_dbThis ) pdf.pdf.debug( evt.address() ); } else for ( auto& pdf : m_matrixElements ) - if ( pdf.pdf.name().find( nameMustContain ) != std::string::npos ) pdf.pdf.debug( evt ); + if ( pdf.pdf.name().find( nameMustContain ) != std::string::npos ) pdf.pdf.debug( evt.address() ); if( evt.cacheSize() != 0 ) INFO( "Pdf = " << prob_unnormalised( evt ) ); INFO( "A(x) = " << getVal(evt) ); } diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 569d3ccad9c..f0b1f5b12b2 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -39,7 +39,7 @@ PolarisedSum::PolarisedSum( const EventType& type, m_eventType(type), m_prefix(prefix) { - bool debug = NamedParameter( "PolarisedSum::Debug" ,false ); + m_debug = NamedParameter( "PolarisedSum::Debug" ,false ); bool autoCompile = NamedParameter( "PolarisedSum::AutoCompile",true ); std::string objCache = NamedParameter("PolarisedSum::ObjectCache","" ); m_verbosity = NamedParameter( "PolarisedSum::Verbosity" ,0 ); @@ -65,7 +65,7 @@ PolarisedSum::PolarisedSum( const EventType& type, CompiledExpression< std::vector , const real_t*, const real_t* > expression( TensorExpression( thisExpression), matrix_element.first.decayDescriptor(), - type.getEventFormat(), debug ? syms : DebugSymbols() ,&mps ); + type.getEventFormat(), m_debug ? syms : DebugSymbols() ,&mps ); m_matrixElements.emplace_back(matrix_element.first, matrix_element.second, expression ); } if(autoCompile){ @@ -226,8 +226,9 @@ void PolarisedSum::reset( const bool& flag ){ m_nCalls = 0 ; } void PolarisedSum::build_probunnormalised() { - auto prob = probExpression(transitionMatrix(), convertProxies(m_pVector,[](auto& p){ return Parameter(p->name());} ) ); - m_probExpression = CompiledExpression(prob, "prob_unnormalised", std::map(), {}, m_mps); + DebugSymbols db; + auto prob = probExpression(transitionMatrix(), convertProxies(m_pVector,[](auto& p){ return Parameter(p->name());} ), m_debug ? &db : nullptr); + m_probExpression = CompiledExpression(prob, "prob_unnormalised", std::map(), db, m_mps); CompilerWrapper().compile(m_probExpression); m_probExpression.prepare(); } @@ -295,13 +296,26 @@ double PolarisedSum::prob(const Event& evt) const void PolarisedSum::debug(const Event& evt) { auto dim = m_eventType.dim(); - size_t size = dim.first * dim.second; + size_t tsize = dim.first * dim.second; for(auto& me : m_matrixElements) { - std::vector this_cache(0,size); - for(size_t i = 0 ; i < size; ++i ) this_cache.emplace_back( evt.getCache(me.addressData+i) ); + std::vector this_cache(0,tsize); + for(size_t i = 0 ; i < tsize; ++i ) this_cache.emplace_back( evt.getCache(me.addressData+i) ); INFO( me.decayDescriptor() << " " << vectorToString( this_cache, " ") ); } + INFO("P(x) = " << getValNoCache(evt) ); + INFO("Prod = [" << vectorToString(m_pVector , ", ") <<"]"); + if( m_debug ) + { + transferParameters(); + Event copy(evt); + copy.resizeCache( size() ); + for(auto& me : m_matrixElements){ + auto values = me(copy); + copy.setCache( values , me.addressData ); + } + m_probExpression.debug( copy.getCachePtr() ); + } } void PolarisedSum::generateSourceCode(const std::string& fname, const double& normalisation, bool add_mt) @@ -340,7 +354,7 @@ void PolarisedSum::generateSourceCode(const std::string& fname, const double& no stream.close(); } -Expression PolarisedSum::probExpression(const Tensor& T_matrix, const std::vector& p) const +Expression PolarisedSum::probExpression(const Tensor& T_matrix, const std::vector& p, DebugSymbols* db) const { Tensor T_conj = T_matrix.conjugate(); Tensor::Index a,b,c; @@ -348,6 +362,28 @@ Expression PolarisedSum::probExpression(const Tensor& T_matrix, const std::vecto size_t it = T_matrix.dims()[0]; Tensor rho = Identity(it); if(it == 2) rho = rho + Sigma[0] * p[0] + Sigma[1] * p[1] + Sigma[2]*p[2]; + if(it == 3) + { + auto px = p[0]; + auto py = p[1]; + auto pz = p[2]; + auto Tyy = p[3]; + auto Tzz = p[4]; + auto Txy = p[5]; + auto Txz = p[6]; + auto Tyz = p[7]; + rho(0,0) = 1 + 1.5 * pz + sqrt(1.5)*Tzz; + rho(1,0) = sqrt(0.375)*(px+1i*py) + sqrt(3.)*(Txz+1i*Tyz); + rho(2,0) = -sqrt(1.5)*( Tzz + 2.*Tyy - 2.*1i*Txy); + rho(0,1) = sqrt(0.375)*(px-1i*py) + sqrt(3.)*(Txz-1i*Tyz); + rho(1,1) = 1 - sqrt(6.)*Tzz; + rho(2,1) = sqrt(0.375)*(px+1i*py) - sqrt(3.)*(Txz+1i*Tyz); + rho(0,2) = -sqrt(1.5)*( Tzz + 2.*Tyy + 2.*1i*Txy); + rho(1,2) = sqrt(0.375)*(px-1i*py) - sqrt(3)*(Txz-1i*Tyz); + rho(2,2) = 1. - 1.5*pz + sqrt(1.5)*Tzz; + } + ADD_DEBUG_TENSOR(rho, db); + ADD_DEBUG_TENSOR(TT , db); Expression rt = rho(a,b) * TT(b,a); return Real(rt); } diff --git a/src/ThreeBodyCalculators.cpp b/src/ThreeBodyCalculators.cpp index a484da7eeb0..d3123d52aab 100644 --- a/src/ThreeBodyCalculators.cpp +++ b/src/ThreeBodyCalculators.cpp @@ -279,7 +279,7 @@ void ThreeBodyCalculator::debug( const double& m, const double& theta ) Event event(12); width.integrator.setEvent({m,theta},event); event.print(); - width.totalWidth.debug( event ); + width.totalWidth.debug( event.address() ); } } From 9c000c57a8e256bb2b8d45de3bda93b3b71f403d Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 9 Jul 2019 16:03:31 +0200 Subject: [PATCH 082/250] Fix instructions for lxplus usage --- README.md | 15 +++++++-------- src/FitResult.cpp | 3 +-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index caa1702d826..9dd1f285f52 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,10 @@ cmake .. make ``` This will build the shared library, several standalone test applications, and a set of unit tests. +Several examples of usages of the library are included in the apps directory and are built alongside the library. +All standalone programs can accept both options files and command line arguments. +They also support `--help` to print help for key arguments to the program. +This will also run the program, as arguments can be defined throughout each of the programs rather than all defined at the beginning. #### Usage with ROOT @@ -74,15 +78,10 @@ is to specifically specify the location of the build tool for AmpGen's JIT: In order to build stand-alone on LXPLUS, you will need a valid development environment; the following line will work: ```shell -lb-run -c x86_64-centos7-gcc62-opt ROOT $SHELL +source /cvmfs/sft.cern.ch/lcg/views/setupViews.sh LCG_94python3 x86_64-centos7-gcc8-opt ``` -Additionally, the ROOT versions installed on cvfms generally require C++17 support when building. - -Several examples of usages of the library are included in the apps directory and are -built alongside the library. -All standalone programs can accept both options files and command line arguments. -They also support `--help` to print help for key arguments to the program. -This will also run the program, as arguments can be defined throughout each of the programs rather than all defined at the beginning. +The LCG versions and CMTCONFIG may need to be updated over time. +The ROOT versions installed on cvmfs generally require C++17 support when building, i.e. when running cmake add the option `-DCMAKE_CXX_STANDARD=17`. ### Options files and decay descriptors diff --git a/src/FitResult.cpp b/src/FitResult.cpp index 5d593e6b06a..4d49ae78a4f 100644 --- a/src/FitResult.cpp +++ b/src/FitResult.cpp @@ -95,7 +95,6 @@ bool FitResult::readFile( const std::string& fname ) size_t nParameters = parameterLines.size(); m_covarianceMatrix.ResizeTo( parameterLines.size(), parameterLines.size() ); for (size_t i = 0; i < nParameters; ++i ) { - INFO("parsing line: " << parameterLines[i] ); auto tokens = split( parameterLines[i], ' ' ); m_covMapping[tokens[1]] = i; m_mps->add( new MinuitParameter( tokens[1], MinuitParameter::Flag(stoi( tokens[2] ) ), stod( tokens[3] ), stod( tokens[4] ), 0, 0 ) ); @@ -135,7 +134,7 @@ void FitResult::writeToFile( const std::string& fname ) auto param = m_mps->at(i); outlog << "Parameter" << " " << param->name() << " " << param->iFixInit() << " " << param->mean() << " " - << m_mps->at(i)->err() << " "; + << ( param->iFixInit() == 0 ? m_mps->at(i)->err() : 0 ) << " "; for (size_t j = 0; j < (size_t)m_covarianceMatrix.GetNcols(); ++j ) outlog << m_covarianceMatrix[i][j] << " "; outlog << std::endl; } From 5936ae967bb49a30d05ff9a3285395a773693c54 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 7 Aug 2019 10:11:19 +0200 Subject: [PATCH 083/250] Fix in python bindings, add linear time-dependent amplitude --- AmpGen/EventList.h | 7 +++---- AmpGen/FitFraction.h | 4 ++-- AmpGen/Lineshapes.h | 12 ++++++++++++ AmpGen/Minimiser.h | 2 -- AmpGen/ParticleProperties.h | 35 +++++++++++++++++----------------- AmpGen/PhaseSpace.h | 2 +- AmpGen/Projection.h | 4 +++- apps/Debugger.cpp | 3 ++- apps/Generator.cpp | 5 ++--- src/CoherentSum.cpp | 1 + src/CompiledExpressionBase.cpp | 2 +- src/Event.cpp | 6 +++++- src/EventList.cpp | 5 +++-- src/EventType.cpp | 3 +-- src/Lineshapes/TD.cpp | 20 +++++++++++++++++++ src/Minimiser.cpp | 6 +++++- src/Particle.cpp | 6 +++--- src/ParticleProperties.cpp | 9 +++++++++ src/PhaseSpace.cpp | 10 ++++++---- src/PolarisedSum.cpp | 1 + src/Projection.cpp | 4 +++- src/Vertex.cpp | 8 +++++++- 22 files changed, 108 insertions(+), 47 deletions(-) create mode 100644 src/Lineshapes/TD.cpp diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 8a7fa280586..16222daf2f3 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -127,7 +127,8 @@ namespace AmpGen } } void reserveCache(const size_t& index); - TH2D* makeProjection( const Projection2D& projection, const ArgumentPack& args ); + TH1D* makeProjection(const Projection& projection , const ArgumentPack& args) const; + TH2D* makeProjection(const Projection2D& projection, const ArgumentPack& args) const; std::vector makeProjections( const std::vector& projections, const ArgumentPack& args ); template @@ -144,12 +145,10 @@ namespace AmpGen return makeProjections( projections, ArgumentPack( args... ) ); } template - TH1D* makeProjection( const Projection& projection, const ARGS&... args ) + TH1D* makeProjection( const Projection& projection, const ARGS&... args ) const { return makeProjection( projection, ArgumentPack(args...) ); } - TH1D* makeProjection( const Projection& projection, const ArgumentPack& args ); - template TH2D* makeProjection( const Projection2D& projection, const ARGS&... args ) { diff --git a/AmpGen/FitFraction.h b/AmpGen/FitFraction.h index 99012395c40..cabdb99767c 100644 --- a/AmpGen/FitFraction.h +++ b/AmpGen/FitFraction.h @@ -82,14 +82,14 @@ namespace AmpGen } return std::real(sum); } - real_t getVal( const size_t& index ) const { + real_t getVal( const size_t& index, const bool& getImaginaryPart = false) const { complex_t sum = 0; for ( auto& i : calculators[index].i ) { for ( auto& j : calculators[index].j ) { sum += (*pdf)[i].coefficient * std::conj( (*pdf)[j].coefficient ) * ( j >= i ? pdf->norm(i, j) : std::conj(pdf->norm(j,i)) ); } } - return std::real(sum) / norm(); + return (getImaginaryPart ? std::imag(sum) : std::real(sum) ) / norm(); } std::vector operator()(const std::string& name, const LinearErrorPropagator& linProp ) { diff --git a/AmpGen/Lineshapes.h b/AmpGen/Lineshapes.h index d9a1dcf095a..4bd0989afe1 100644 --- a/AmpGen/Lineshapes.h +++ b/AmpGen/Lineshapes.h @@ -383,6 +383,18 @@ namespace AmpGen */ DECLARE_LINESHAPE( EtaDalitz ); + /** @ingroup Lineshapes class TD + @brief (Linear) time dependence + + ''Lineshape'' that gives a linear time-dependence for use in time-dependent generation / fitting. + @f[ + \mathcal{A}(t) = \frac{t}{2\tau}, + @f] + where @f$\tau@f$ is the proper decay time. + + */ + DECLARE_LINESHAPE( TD ); + DECLARE_LINESHAPE( Photon ); } // namespace Lineshape diff --git a/AmpGen/Minimiser.h b/AmpGen/Minimiser.h index e6940a6ab3a..5596c34cd1f 100644 --- a/AmpGen/Minimiser.h +++ b/AmpGen/Minimiser.h @@ -50,9 +50,7 @@ namespace AmpGen void prepare(); bool doFit(); void GradientTest(); - TGraph* scan( MinuitParameter* param, const double& min, const double& max, const double& step ); - void addExtendedTerm( IExtendLikelihood* term ); TMatrixTSym covMatrix() const; TMatrixTSym covMatrixFull() const; diff --git a/AmpGen/ParticleProperties.h b/AmpGen/ParticleProperties.h index d2ce1e921de..0e395000a47 100644 --- a/AmpGen/ParticleProperties.h +++ b/AmpGen/ParticleProperties.h @@ -47,30 +47,31 @@ namespace AmpGen int chargeFromString( const std::string& ch, bool& status ) const; public: - double mass() const { return m_mass * MeV; } ///< returns mass of particle in MeV - double mErrPlus() const { return m_mErrPlus * MeV; } ///< returns +ve uncertainty on particle mass in MeV + double mass() const { return m_mass * MeV; } ///< returns mass of particle in MeV + double mErrPlus() const { return m_mErrPlus * MeV; } ///< returns +ve uncertainty on particle mass in MeV double mErrMinus() const { return m_mErrMinus * MeV; } ///< returns -ve uncertainty on particle mass in MeV - double width() const { return m_width * MeV; } ///< returns width of particle in MeV - double wErrPlus() const { return m_wErrPlus * MeV; } ///< returns +ve uncertainty on particle width in MeV + double width() const { return m_width * MeV; } ///< returns width of particle in MeV + double wErrPlus() const { return m_wErrPlus * MeV; } ///< returns +ve uncertainty on particle width in MeV double wErrMinus() const { return m_wErrMinus * MeV; } ///< returns -ve uncertainty on particle width in MeV - double radius() const; + double radius() const; ///< returns the effective interaction radius of the particle, i.e. for the Blatt-Weisskopf factors + double lifetime() const; ///< returns the lifetime of the particle in ns - int G() const { return m_Gparity; } - int P() const { return m_parity; } - int C() const { return m_Cparity; } - int R() const { return m_Rexist; } - int pdgID() const { return m_pdgID; } - int twoSpin() const { return m_twoSpin ; } - std::string I() const { return m_isospin; } - std::string J() const { return m_JtotalSpin; } - int charge() const { return m_charge; } - std::string label() const { return m_texName; } + int G() const { return m_Gparity; } ///< returns the G-parity of the particle + int P() const { return m_parity; } ///< returns the parity of the particle + int C() const { return m_Cparity; } ///< returns the C-parity of the particle + int R() const { return m_Rexist; } + int pdgID() const { return m_pdgID; } + int twoSpin() const { return m_twoSpin; } + int charge() const { return m_charge; } + char S() const { return m_status; } + std::string I() const { return m_isospin; } + std::string J() const { return m_JtotalSpin; } + std::string label() const { return m_texName; } std::string quarks() const { return m_quarks; } - std::string name() const; + std::string name() const; std::string chargeString() const { return m_chargeString; } std::string spinName() const; - char S() const { return m_status; } void setLabel( const std::string& label ) { m_texName = label; } void setName( const std::string& name ) { m_name = name; } const QuarkContent& netQuarkContent() const { return m_netQuarkContent; } diff --git a/AmpGen/PhaseSpace.h b/AmpGen/PhaseSpace.h index d44a8386635..ecd2b578ee2 100644 --- a/AmpGen/PhaseSpace.h +++ b/AmpGen/PhaseSpace.h @@ -34,7 +34,7 @@ namespace AmpGen AmpGen::EventType eventType() const; private: - unsigned int m_nt = {0}; // number of decay particles + size_t m_nt = {0}; // number of decay particles double m_mass[18] = {0}; // masses of particles double m_teCmTm = {0}; // total energy in the C.M. minus the total mass double m_wtMax = {0}; // maximum weight diff --git a/AmpGen/Projection.h b/AmpGen/Projection.h index 9869249a0f5..7e20fb8fbb4 100644 --- a/AmpGen/Projection.h +++ b/AmpGen/Projection.h @@ -8,7 +8,7 @@ #include "TH1D.h" #include "TH2D.h" -#include "AmpGen/Event.h" +//#include "AmpGen/Event.h" class TH1D; class TH2D; @@ -17,6 +17,7 @@ namespace AmpGen { class Projection2D; class Event; + class EventList; class Projection { @@ -33,6 +34,7 @@ namespace AmpGen public: const std::string name() const ; double operator()( const Event& evt ) const ; + TH1D* operator()(const EventList& evt) const; template Projection( const FCN& fcn, const std::string& name, const std::string& xAxisTitle, const size_t& nBins, const double& min, const double& max, diff --git a/apps/Debugger.cpp b/apps/Debugger.cpp index 5bf0d9bb58b..5da93c41b4c 100644 --- a/apps/Debugger.cpp +++ b/apps/Debugger.cpp @@ -113,7 +113,8 @@ int main( int argc, char** argv ) int seed = NamedParameter( "Seed", 156 ); TRandom3* rndm = new TRandom3( seed ); - EventType eventType( NamedParameter( "EventType" ).getVector() ); + EventType eventType( NamedParameter( "EventType" , "", "EventType to generate, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(), + NamedParameter( "GenerateTimeDependent", false , "Flag to include possible time dependence of the amplitude") ); bool verbose = NamedParameter("CoherentSum::Debug", 0 ) || NamedParameter("PolarisedSum::Debug", 0 ); diff --git a/apps/Generator.cpp b/apps/Generator.cpp index 315cfb3049c..84470cdd9c4 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -97,6 +97,7 @@ int main( int argc, char** argv ) EventType eventType( NamedParameter( "EventType" , "", "EventType to generate, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(), NamedParameter( "GenerateTimeDependent", false , "Flag to include possible time dependence of the amplitude") ); + INFO("Generating time-dependence? " << eventType.isTimeDependent() ); EventList accepted( eventType ); INFO("Generating events with type = " << eventType ); @@ -137,13 +138,11 @@ int main( int argc, char** argv ) auto proj = eventType.defaultProjections(nBins); INFO("Making 2D projections..."); for( size_t i = 0 ; i < proj.size(); ++i ){ - for( size_t j = i+1 ; j < proj.size(); ++j ){ - + for( size_t j = i+1 ; j < proj.size(); ++j ){ accepted.makeProjection( Projection2D(proj[i],proj[j] ) )->Write(); } } } - INFO( "Writing output file " ); f->Close(); diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 8dfb4c4c88e..8cef77954a1 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -123,6 +123,7 @@ void CoherentSum::debug( const Event& evt, const std::string& nameMustContain ) << " A = [ " << std::real(A) << " " << std::imag(A) << " ] g = [ "<< std::real(pdf.coupling()) << " " << std::imag(pdf.coupling()) << " ]" ); if( m_dbThis ) pdf.pdf.debug( evt.address() ); + pdf.coupling.print(); } else for ( auto& pdf : m_matrixElements ) diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index 7785bf54882..1e71a632144 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -99,7 +99,7 @@ void CompiledExpressionBase::to_stream( std::ostream& stream ) const stream << " r[i] = " << m_obj.to_string(m_resolver) << ";\n}\n"; } - if( NamedParameter("IncludePythonBindings", false) == true ){ + if( NamedParameter("IncludePythonBindings", false) == true && returnTypename().find("complex") != std::string::npos ){ // stream << "#pragma clang diagnostic pop\n\n"; stream << "extern \"C\" void " << progName() << "_c" << "(double *real, double *imag, " << fcnSignature() << "){\n"; stream << " auto val = " << progName() << "(" << args() << ") ;\n"; diff --git a/src/Event.cpp b/src/Event.cpp index 483267fb15f..d9535000906 100644 --- a/src/Event.cpp +++ b/src/Event.cpp @@ -21,7 +21,8 @@ Event::Event( const real_t* data, const size_t& N, const size_t& cacheSize) : } void Event::print() const { - for( unsigned int i = 0 ; i< m_event.size()/4 ; ++i ){ + size_t nParticles = m_event.size()/4; + for( size_t i = 0 ; i < nParticles; ++i ){ double px = m_event[4*i+0]; double py = m_event[4*i+1]; double pz = m_event[4*i+2]; @@ -29,6 +30,9 @@ void Event::print() const { double s = pE*pE - px*px -py*py -pz*pz; INFO( "P["<& bool EventType::operator==( const EventType& other ) const { if ( m_mother != other.mother() || size() != other.size() ) return false; - for ( size_t i = 0; i < m_particleNames.size(); ++i ) { if ( m_particleNames[i] != other[i] ) return false; } diff --git a/src/Lineshapes/TD.cpp b/src/Lineshapes/TD.cpp new file mode 100644 index 00000000000..6bfd744cec6 --- /dev/null +++ b/src/Lineshapes/TD.cpp @@ -0,0 +1,20 @@ +#include +#include +#include + +#include "AmpGen/Expression.h" +#include "AmpGen/Factory.h" +#include "AmpGen/Lineshapes.h" +#include "AmpGen/Tensor.h" +#include "AmpGen/ParticleProperties.h" + +using namespace AmpGen; +using namespace AmpGen::fcn; + +DEFINE_GENERIC_SHAPE( TD ) +{ + Expression tau = Parameter(p.name() +"_decayTime"); + ADD_DEBUG( tau, dbexpressions ); + ADD_DEBUG( p.props()->lifetime(), dbexpressions ); + return tau / ( 2 * p.props()->lifetime() ); +} diff --git a/src/Minimiser.cpp b/src/Minimiser.cpp index e0d4514c540..af5a6c4c6e2 100644 --- a/src/Minimiser.cpp +++ b/src/Minimiser.cpp @@ -116,7 +116,11 @@ bool Minimiser::doFit() for ( unsigned int j = 0; j < m_nParams; ++j ) { m_covMatrix[i + m_nParams * j] = m_minimiser->CovMatrix( i, j ); } - } +// double up, down; +// double v = *(m_minimiser->X() +i); +// m_minimiser->GetMinosError(i, up, down); +// INFO( par->name() << " " << v << " " << par->mean() << " " << up << " " << down << " " << error ); + } m_status = m_minimiser->Status(); return 1; } diff --git a/src/Particle.cpp b/src/Particle.cpp index 8bfca42f9ea..5073aa59e09 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -124,7 +124,9 @@ Particle::Particle( const std::string& name, const unsigned int& index ) : Parti void Particle::parseModifier( const std::string& mod ) { - if( mod.size() == 1 ) + if ( Lineshape::Factory::isLineshape( mod ) ) + m_lineshape = mod; + else if( mod.size() == 1 ) { DEBUG( "Modifier = " << mod ); if ( mod == "S" ) m_orbital = 0; @@ -143,8 +145,6 @@ void Particle::parseModifier( const std::string& mod ) parseModifier( mod.substr(0,1) ); parseModifier( mod.substr(1,1) ); } - else if ( Lineshape::Factory::isLineshape( mod ) ) - m_lineshape = mod; } double Particle::spin() const { return double( m_props->twoSpin() / 2. ) ; } diff --git a/src/ParticleProperties.cpp b/src/ParticleProperties.cpp index 0be1b6d97ec..4c460e3dad5 100644 --- a/src/ParticleProperties.cpp +++ b/src/ParticleProperties.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "AmpGen/ParticlePropertiesList.h" #include "AmpGen/MsgService.h" @@ -91,6 +92,8 @@ void ParticleProperties::setRadius() m_radius = isCharm ? defaultCharmRadius : defaultRadius; } + + void ParticleProperties::antiQuarks() { if ( m_quarks.empty() ) return; @@ -144,6 +147,12 @@ std::string ParticleProperties::name() const } double ParticleProperties::radius() const { return m_radius; } +double ParticleProperties::lifetime() const +{ + return 6.582119514 / ( m_width * std::pow( 10, 13 ) ); +} + + bool ParticleProperties::isNonResonant() const { return m_name.find("NonRes") != std::string::npos ; diff --git a/src/PhaseSpace.cpp b/src/PhaseSpace.cpp index 246b8b17f66..d87d8307671 100644 --- a/src/PhaseSpace.cpp +++ b/src/PhaseSpace.cpp @@ -21,8 +21,10 @@ PhaseSpace::PhaseSpace( const EventType& type, TRandom* rand ) : m_rand(rand), m_type(type) { setDecay( type.motherMass(), type.masses() ); - if ( type.isTimeDependent() ) - m_decayTime = 6.582119514 / ( ParticlePropertiesList::get( type.mother() )->width() * pow( 10, 13 ) ); + if ( type.isTimeDependent() ){ + INFO("Generating with time-dependence"); + m_decayTime = ParticlePropertiesList::get( type.mother() )->lifetime(); + } } PhaseSpace::PhaseSpace( const Particle& particle, TRandom* rand ) : @@ -38,10 +40,10 @@ Event PhaseSpace::makeEvent(const size_t& cacheSize) std::array rno; std::array pd; std::array invMas; - Event rt( 4 * m_nt, cacheSize); + Event rt(4*m_nt + m_type.isTimeDependent(), cacheSize); rno[0] = 0; - unsigned int n; + size_t n; double wt = m_wtMax; do { diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index f0b1f5b12b2..6e8f260e020 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -382,6 +382,7 @@ Expression PolarisedSum::probExpression(const Tensor& T_matrix, const std::vecto rho(1,2) = sqrt(0.375)*(px-1i*py) - sqrt(3)*(Txz-1i*Tyz); rho(2,2) = 1. - 1.5*pz + sqrt(1.5)*Tzz; } + ADD_DEBUG_TENSOR(T_matrix, db); ADD_DEBUG_TENSOR(rho, db); ADD_DEBUG_TENSOR(TT , db); Expression rt = rho(a,b) * TT(b,a); diff --git a/src/Projection.cpp b/src/Projection.cpp index 5a08fbaa0a9..f11ba7a1828 100644 --- a/src/Projection.cpp +++ b/src/Projection.cpp @@ -1,6 +1,7 @@ #include "AmpGen/Projection.h" #include "AmpGen/Utilities.h" #include "AmpGen/Event.h" +#include "AmpGen/EventList.h" #include #include "TAxis.h" @@ -9,7 +10,7 @@ using namespace AmpGen; -Projection::Projection(){} +Projection::Projection() = default; Projection::Projection( const std::function& fcn, const std::string& name, const std::string& xAxisTitle, @@ -69,3 +70,4 @@ std::pair Projection2D::operator()( const Event& evt ) const return {xAxis.m_func( evt ), yAxis.m_func( evt )}; } +TH1D* Projection::operator()( const EventList& events) const { return events.makeProjection(*this); } diff --git a/src/Vertex.cpp b/src/Vertex.cpp index 11a8557bf4b..2fb2ee72535 100644 --- a/src/Vertex.cpp +++ b/src/Vertex.cpp @@ -240,12 +240,18 @@ DEFINE_VERTEX( V_TS_D ) DEFINE_VERTEX( f_fS_S ) { - return Spin1hProjector(P)(a,b) * V1(b) * V2[0]; + Tensor f_fS_Sv = Spin1hProjector(P)(a,b) * V1(b) * V2[0]; + ADD_DEBUG_TENSOR( f_fS_Sv, db); + return f_fS_Sv; } + DEFINE_VERTEX( f_fS_P ) { Tensor proj = Spin1hProjector(P); Tensor L = Orbital_PWave(P,Q); + ADD_DEBUG_TENSOR( P, db ); + ADD_DEBUG_TENSOR( Q, db ); + ADD_DEBUG_TENSOR( L, db ); Tensor t = proj(a, b) * Gamma[4](b,c) * slash(L)(c,d) * V1(d); return t; } From fb06e0c5e611bcc05fd4901a80682f551989c392 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 13 Aug 2019 17:38:17 +0200 Subject: [PATCH 084/250] Add pretty new enums, some cleanup of the variable flagging code --- AmpGen/EventList.h | 26 +++++----- AmpGen/MetaUtils.h | 2 + AmpGen/Minimiser.h | 2 - AmpGen/MinuitExpression.h | 8 ++-- AmpGen/MinuitParameter.h | 23 ++++----- AmpGen/Projection.h | 47 ++++++++++--------- AmpGen/enum.h | 47 +++++++++++++++++++ apps/Fitter.cpp | 14 +++--- apps/Generator.cpp | 3 +- examples/QcGenerator.cpp | 2 +- src/ASTResolver.cpp | 3 +- src/AmplitudeRules.cpp | 3 +- src/ErrorPropagator.cpp | 6 +-- src/FitResult.cpp | 14 +++--- src/Lineshapes/BW.cpp | 1 + src/Minimiser.cpp | 38 +-------------- src/MinuitParameter.cpp | 34 +++++++------- src/MinuitParameterSet.cpp | 86 ++++++++++++---------------------- src/Spline.cpp | 2 +- src/Wigner.cpp | 11 +++-- test/test_AmplitudeRules.cpp | 20 ++++---- test/test_ExpressionParser.cpp | 10 ++-- 22 files changed, 196 insertions(+), 206 deletions(-) create mode 100644 AmpGen/enum.h diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 16222daf2f3..a0b58fdbb33 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -24,6 +24,7 @@ namespace AmpGen { + DECLARE_ARGUMENT(Bins, size_t); class CompiledExpressionBase; @@ -127,41 +128,42 @@ namespace AmpGen } } void reserveCache(const size_t& index); - TH1D* makeProjection(const Projection& projection , const ArgumentPack& args) const; - TH2D* makeProjection(const Projection2D& projection, const ArgumentPack& args) const; + TH1D* makeProjection(const Projection& projection , const ArgumentPack& args = ArgumentPack()) const; + TH2D* makeProjection(const Projection2D& projection, const ArgumentPack& args = ArgumentPack()) const; std::vector makeProjections( const std::vector& projections, const ArgumentPack& args ); - template - std::vector makeDefaultProjections( const ARGS&... args ) + template std::vector makeDefaultProjections( const ARGS&... args ) { auto argPack = ArgumentPack( args... ); size_t nBins = argPack.getArg(100); auto proj = eventType().defaultProjections(nBins); return makeProjections( proj , argPack ); } - template - std::vector makeProjections( const std::vector& projections, const ARGS&... args ) + + template std::vector makeProjections( const std::vector& projections, const ARGS&... args ) { return makeProjections( projections, ArgumentPack( args... ) ); } - template + + template ::type, ArgumentPack> = 0 > TH1D* makeProjection( const Projection& projection, const ARGS&... args ) const { return makeProjection( projection, ArgumentPack(args...) ); } - template + + template ::type, ArgumentPack> = 0 > TH2D* makeProjection( const Projection2D& projection, const ARGS&... args ) { return makeProjection( projection, ArgumentPack(args...) ); } - template - EventList& transform( FCN&& fcn ) + + template EventList& transform( FCN&& fcn ) { for ( auto& event : m_data ) fcn( event ); return *this; } - template - void filter( FCN&& fcn ){ + + template void filter( FCN&& fcn ){ size_t currentSize = size(); m_data.erase( std::remove_if( m_data.begin(), m_data.end(), fcn ) , m_data.end() ); INFO("Filter removes: " << currentSize - size() << " / " << currentSize << " events"); diff --git a/AmpGen/MetaUtils.h b/AmpGen/MetaUtils.h index 31985fe437e..8f83aace4f7 100644 --- a/AmpGen/MetaUtils.h +++ b/AmpGen/MetaUtils.h @@ -26,6 +26,8 @@ namespace AmpGen template std::string typeof( TYPE t ) { return typeof(); } + template struct zeroType { typedef T type; }; + template typename std::enable_if::type for_each( std::tuple&, FuncT ){} diff --git a/AmpGen/Minimiser.h b/AmpGen/Minimiser.h index 5596c34cd1f..ea48dbcd40c 100644 --- a/AmpGen/Minimiser.h +++ b/AmpGen/Minimiser.h @@ -49,7 +49,6 @@ namespace AmpGen unsigned int nPars() const; void prepare(); bool doFit(); - void GradientTest(); TGraph* scan( MinuitParameter* param, const double& min, const double& max, const double& step ); void addExtendedTerm( IExtendLikelihood* term ); TMatrixTSym covMatrix() const; @@ -61,7 +60,6 @@ namespace AmpGen ROOT::Math::Minimizer* minimiserInternal(); private: - void print( const double& LL ); MinuitParameterSet* m_parSet = {nullptr}; std::function m_theFunction; ROOT::Math::Minimizer* m_minimiser = {nullptr}; diff --git a/AmpGen/MinuitExpression.h b/AmpGen/MinuitExpression.h index f4a7179e5e3..f6f246202dc 100644 --- a/AmpGen/MinuitExpression.h +++ b/AmpGen/MinuitExpression.h @@ -14,10 +14,6 @@ namespace AmpGen class MinuitExpression : public MinuitParameter { - private: - Expression m_expression; - bool m_isGood; - public: MinuitExpression( const std::vector& tokens, MinuitParameterSet* mps ); double getVal() const { return std::real( m_expression() ); } @@ -25,6 +21,10 @@ namespace AmpGen operator double() const override { return getVal(); } ~MinuitExpression() override = default; bool isGood() const { return m_isGood; } + + private: + Expression m_expression; + bool m_isGood; }; } // namespace AmpGen diff --git a/AmpGen/MinuitParameter.h b/AmpGen/MinuitParameter.h index 6544084631f..3cecd0ed778 100644 --- a/AmpGen/MinuitParameter.h +++ b/AmpGen/MinuitParameter.h @@ -5,25 +5,26 @@ #include #include +#include "AmpGen/enum.h" namespace AmpGen { class MinuitParameterSet; + declare_enum( Flag, Free, Hide, Fix, CompileTimeConstant ) class MinuitParameter { public: - enum Flag { Float, Hide, Fix, CompileTimeConstant }; - + MinuitParameter() = default; - MinuitParameter(const std::string& name, const Flag& iFixInit, const double& mean, const double& step, + MinuitParameter(const std::string& name, const Flag& flag, const double& mean, const double& step, const double& min = 0, const double& max = 0 ); MinuitParameter(const std::string& name, const double& mean, const double& step, const double& min = 0, const double& max = 0 ); - Flag iFixInit() const; - bool hidden() const; - bool fixed(); + Flag flag() const; + bool isFixed() const; + bool isFree() const; const std::string& name() const; double meanInit() const; @@ -44,7 +45,6 @@ namespace AmpGen void setLimits( const double& min, const double& max ); void setResult( double fitMean, double fitErr, double fitErrPos, double fitErrNeg ); void resetToInit(); - void print( std::ostream& os = std::cout ) const; void setName( const std::string& name ); virtual double mean() const; virtual operator double() const { return m_meanResult; } @@ -52,7 +52,7 @@ namespace AmpGen friend class MinuitParameterSet; private: - Flag m_iFixInit; + Flag m_flag; std::string m_name; double m_meanInit; double m_stepInit; @@ -66,9 +66,6 @@ namespace AmpGen class MinuitProxy { - double m_value; - MinuitParameter* m_parameter; - public: void update() { m_value = m_parameter->mean(); } MinuitParameter* ptr() { return m_parameter; } @@ -77,7 +74,11 @@ namespace AmpGen MinuitProxy( MinuitParameter* param = nullptr ) : m_parameter( param ) { if( m_parameter != nullptr ) update(); } MinuitParameter* operator->() { return m_parameter; } const MinuitParameter* operator->() const { return m_parameter; } + private: + double m_value; + MinuitParameter* m_parameter; }; + std::ostream& operator<<( std::ostream& os, const MinuitParameter& type ); } // namespace AmpGen #endif diff --git a/AmpGen/Projection.h b/AmpGen/Projection.h index 7e20fb8fbb4..393139cfd35 100644 --- a/AmpGen/Projection.h +++ b/AmpGen/Projection.h @@ -21,32 +21,33 @@ namespace AmpGen class Projection { - friend class Projection2D; - private: - std::function m_func; - std::string m_name; - std::string m_xAxisTitle; - std::string m_units; - size_t m_nBins; - double m_min; - double m_max; - double m_width; public: - const std::string name() const ; - double operator()( const Event& evt ) const ; - TH1D* operator()(const EventList& evt) const; - template - Projection( const FCN& fcn, const std::string& name, + Projection(); + template + Projection( const FCN& fcn, const std::string& name, + const std::string& xAxisTitle, const size_t& nBins, const double& min, const double& max, + const std::string& units = "" ) : Projection( std::function< double( const Event& )>( fcn ), name, xAxisTitle, nBins, min, max, units ) {} + Projection( const std::function& fcn, const std::string& name, const std::string& xAxisTitle, const size_t& nBins, const double& min, const double& max, - const std::string& units = "" ) : Projection( std::function< double( const Event& )>( fcn ), name, xAxisTitle, nBins, min, max, units ) {} - Projection( const std::function& fcn, const std::string& name, - const std::string& xAxisTitle, const size_t& nBins, const double& min, const double& max, - const std::string& units = "" ); - Projection(); - TH1D* plot(const std::string& prefix="") const; + const std::string& units = "" ); + const std::string name() const ; + double operator()( const Event& evt ) const ; + TH1D* operator()(const EventList& evt) const; + TH1D* plot(const std::string& prefix="") const; + + std::function binFunctor() const; + void setRange( const double& min, const double& max ){ m_min = (min); m_max = (max) ; } - std::function binFunctor() const; - void setRange( const double& min, const double& max ){ m_min = (min); m_max = (max) ; } + friend class Projection2D; + private: + std::function m_func; + std::string m_name; + std::string m_xAxisTitle; + std::string m_units; + size_t m_nBins; + double m_min; + double m_max; + double m_width; }; class Projection2D diff --git a/AmpGen/enum.h b/AmpGen/enum.h new file mode 100644 index 00000000000..58eefc2d7e4 --- /dev/null +++ b/AmpGen/enum.h @@ -0,0 +1,47 @@ +#include "AmpGen/MsgService.h" + +#define declare_enum(name, ...) enum name {__VA_ARGS__}; \ +template T parse(const std::string& word){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::parse(word, args); } \ +template std::string to_string( const T& enumItem ){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::to_string(enumItem, args) ; } + +namespace AmpGen { + namespace detail { + template T parse(const std::string& word, const char* args) + { + char* p; + auto number = strtoul( word.c_str(), &p, 10 ); + if( *p == 0 ) return T(number); + size_t counter = 0; + size_t begin = 0; + size_t end = 0; + auto compare = [](const char* word, const char* otherWord, const size_t& nChar) + { + for( size_t x = 0; x != nChar ; ++x) if( word[x] != otherWord[x] ) return false; + return true; + }; + for( ; args[begin] != '\0' ; begin++ ) + { + while( args[begin] == ' ' ) begin++; + for( end=begin; args[end] != '\0'; end++ ) if( args[end] == ',' ) break; + if( compare( word.c_str(), args + begin , end-begin ) ) break; + begin = end; + counter++; + } + if( args[begin] == '\0' ) return T(counter-1); + return T(counter); + } + template std::string to_string(const T& enumItem, const char* args) + { + size_t counter = 0; + size_t sBegin = 0; + size_t sLength = 0; + for( ; args[sBegin] != '\0' && counter != enumItem; sBegin++ ) + { + if( args[sBegin] == ',' ) counter++; + } + while( args[sBegin] == ' ') sBegin++; + for(; args[sLength + sBegin] != '\0' ; ++sLength ) if( args[sBegin + sLength] == ',') break; + return std::string(args).substr(sBegin, sLength); + } + } +} diff --git a/apps/Fitter.cpp b/apps/Fitter.cpp index a9c839a4f32..43315e7412f 100644 --- a/apps/Fitter.cpp +++ b/apps/Fitter.cpp @@ -52,13 +52,11 @@ void randomizeStartingPoint( MinuitParameterSet& MPS, TRandom3& rand, bool Splin { double range = 5; for (auto& param : MPS) { - if ( param->iFixInit() == 0 ) { - if ( SplineOnly && param->name().find( "::Spline::" ) == std::string::npos ) continue; - range = param->maxInit() - param->minInit(); - param->setInit( range * rand.Rndm() + param->meanInit() ); - param->print(); - std::cout << std::endl; - } + if ( ! param->isFree() == 0 ) continue; + if ( SplineOnly && param->name().find( "::Spline::" ) == std::string::npos ) continue; + range = param->maxInit() - param->minInit(); + param->setInit( range * rand.Rndm() + param->meanInit() ); + std::cout << *param << std::endl; } } @@ -205,7 +203,7 @@ int main( int argc, char* argv[] ) if ( perturb ) { for ( auto& param : MPS ) { - if ( param->iFixInit() != 0 ) continue; + if ( !param->isFree() ) continue; param->setCurrentFitVal( rndm.Gaus( param->mean(), param->err() ) ); } } diff --git a/apps/Generator.cpp b/apps/Generator.cpp index 84470cdd9c4..543bb5fe4aa 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -136,10 +136,9 @@ int main( int argc, char** argv ) for ( auto& plot : plots ) plot->Write(); if( NamedParameter("plots_2d",true) == true ){ auto proj = eventType.defaultProjections(nBins); - INFO("Making 2D projections..."); for( size_t i = 0 ; i < proj.size(); ++i ){ for( size_t j = i+1 ; j < proj.size(); ++j ){ - accepted.makeProjection( Projection2D(proj[i],proj[j] ) )->Write(); + accepted.makeProjection( Projection2D(proj[i], proj[j]), LineColor(kBlack) )->Write(); } } } diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp index 6867b34bfea..653c32d5aff 100644 --- a/examples/QcGenerator.cpp +++ b/examples/QcGenerator.cpp @@ -335,7 +335,7 @@ void add_CP_conjugate( MinuitParameterSet& mps ) } } if( mps.find( new_name ) == nullptr ){ - tmp.push_back( new MinuitParameter(new_name, MinuitParameter::Flag::Float, sgn * param->mean(), param->err(), 0, 0)); + tmp.push_back( new MinuitParameter(new_name, Flag::Free, sgn * param->mean(), param->err(), 0, 0)); } } for( auto& p : tmp ) mps.add( p ); diff --git a/src/ASTResolver.cpp b/src/ASTResolver.cpp index 6e308309e16..001830e25bf 100644 --- a/src/ASTResolver.cpp +++ b/src/ASTResolver.cpp @@ -114,8 +114,7 @@ template <> void ASTResolver::resolve( const Parameter& parameter ) else if( m_mps != nullptr ){ auto it = m_mps->find(parameter.name()); if( it != nullptr ){ - if( m_enable_compileTimeConstants && - it->iFixInit() == MinuitParameter::Flag::CompileTimeConstant ){ + if( m_enable_compileTimeConstants && it->flag() == Flag::CompileTimeConstant ){ addResolvedParameter( ¶meter, "("+std::to_string(it->mean()) +")" ); } else addResolvedParameter( ¶meter, addCacheFunction( parameter.name(), it ) ); diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index c70cc4a353b..89d0ed39b5d 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -34,7 +34,6 @@ AmplitudeRule::AmplitudeRule(MinuitParameter* re, MinuitParameter* im ) : m_particle = Particle(m_name); } - AmplitudeRules::AmplitudeRules( const MinuitParameterSet& mps ) { for ( auto& it_re : mps ) { @@ -185,7 +184,7 @@ std::vector> AmplitudeRules::getMatchingRu bool CouplingConstant::isFixed() const { return std::all_of( couplings.begin(), couplings.end(), - [](auto& c){ return c.first->iFixInit() != 0 && c.second->iFixInit() != 0 ; } ); + [](auto& c){ return c.first->isFixed() && c.second->isFixed() ; } ); } bool CouplingConstant::contains( const std::string& label ) const diff --git a/src/ErrorPropagator.cpp b/src/ErrorPropagator.cpp index 47da3e8d449..1d22a3fa192 100644 --- a/src/ErrorPropagator.cpp +++ b/src/ErrorPropagator.cpp @@ -59,8 +59,7 @@ LinearErrorPropagator::LinearErrorPropagator( const TMatrixD& reducedCovarianceM LinearErrorPropagator::LinearErrorPropagator( const std::vector& params ) { for( auto& param : params ){ - if( param->iFixInit() != MinuitParameter::Float ) continue; - if( param->err() == 0 ) continue; + if( !param->isFree() || param->err() == 0 ) continue; m_parameters.push_back( param ); } m_cov.ResizeTo( m_parameters.size(), m_parameters.size() ); @@ -71,8 +70,7 @@ LinearErrorPropagator::LinearErrorPropagator( const std::vectoriFixInit() != MinuitParameter::Float ) continue; - if( param->err() == 0 ) continue; + if( ! param->isFree() || param->err() == 0 ) continue; m_parameters.push_back(param); } m_cov.ResizeTo( m_parameters.size(), m_parameters.size() ); diff --git a/src/FitResult.cpp b/src/FitResult.cpp index 4d49ae78a4f..5126199f05c 100644 --- a/src/FitResult.cpp +++ b/src/FitResult.cpp @@ -55,7 +55,7 @@ FitResult::FitResult( const Minimiser& mini ) m_status = mini.status(); m_nParam = 0; for (size_t i = 0; i < m_mps->size(); ++i ) { - if ( m_mps->at(i)->iFixInit() == 0 ) m_nParam++; + if ( m_mps->at(i)->isFree() ) m_nParam++; m_covMapping[ m_mps->at(i)->name() ] = i; } } @@ -69,7 +69,7 @@ FitResult::FitResult( const MinuitParameterSet& mps, const TMatrixD& covMini ) : m_covarianceMatrix.ResizeTo( covMini.GetNcols(), covMini.GetNrows() ); m_covarianceMatrix = covMini; for (size_t i = 0; i < m_mps->size(); ++i ) { - if ( m_mps->at(i)->iFixInit() == 0 ) m_nParam++; + if ( m_mps->at(i)->isFree()) m_nParam++; } } @@ -97,7 +97,7 @@ bool FitResult::readFile( const std::string& fname ) for (size_t i = 0; i < nParameters; ++i ) { auto tokens = split( parameterLines[i], ' ' ); m_covMapping[tokens[1]] = i; - m_mps->add( new MinuitParameter( tokens[1], MinuitParameter::Flag(stoi( tokens[2] ) ), stod( tokens[3] ), stod( tokens[4] ), 0, 0 ) ); + m_mps->add( new MinuitParameter( tokens[1], parse(tokens[2]), stod( tokens[3] ), stod( tokens[4] ), 0, 0 ) ); for (size_t j = 0; j < nParameters; ++j ) m_covarianceMatrix( i, j ) = stod( tokens[5 + j] ); } return true; @@ -133,8 +133,8 @@ void FitResult::writeToFile( const std::string& fname ) for (size_t i = 0; i < (size_t)m_covarianceMatrix.GetNrows(); ++i ) { auto param = m_mps->at(i); outlog << "Parameter" - << " " << param->name() << " " << param->iFixInit() << " " << param->mean() << " " - << ( param->iFixInit() == 0 ? m_mps->at(i)->err() : 0 ) << " "; + << " " << param->name() << " " << param->flag() << " " << param->mean() << " " + << ( param->isFree() ? m_mps->at(i)->err() : 0 ) << " "; for (size_t j = 0; j < (size_t)m_covarianceMatrix.GetNcols(); ++j ) outlog << m_covarianceMatrix[i][j] << " "; outlog << std::endl; } @@ -165,7 +165,7 @@ std::vector FitResult::floating( const bool& extended ) const { std::vector floating; for ( auto& param : *m_mps ) { - if ( ( param->iFixInit() == 0 || extended ) && param->err() > 1e-6 ) floating.push_back( param ); + if ( ( param->isFree() || extended ) && param->err() > 1e-6 ) floating.push_back( param ); } return floating; } @@ -175,7 +175,7 @@ TMatrixD FitResult::getReducedCovariance( const bool& extended ) const std::vector floating_indices; for (size_t i = 0; i < m_mps->size(); ++i ) { auto param = m_mps->at(i); - if ( ( param->iFixInit() == 0 || extended ) && param->err() > 1e-6 ) floating_indices.push_back( i ); + if ( ( param->isFree() || extended ) && param->err() > 1e-6 ) floating_indices.push_back( i ); } TMatrixD reducedCov( floating_indices.size(), floating_indices.size() ); if ( int( floating_indices.size() ) > m_covarianceMatrix.GetNrows() ) { diff --git a/src/Lineshapes/BW.cpp b/src/Lineshapes/BW.cpp index 082e2740c00..14fe2e6ea72 100644 --- a/src/Lineshapes/BW.cpp +++ b/src/Lineshapes/BW.cpp @@ -27,6 +27,7 @@ DEFINE_LINESHAPE( FormFactor ) Expression FormFactor = sqrt( BlattWeisskopf_Norm( q2 * radius * radius, 0, Lp ) ); if ( lineshapeModifier == "BL" ) FormFactor = sqrt( BlattWeisskopf( q2 * radius * radius, Lp ) ); + if ( lineshapeModifier == "NFF" ) FormFactor = 1; if ( lineshapeModifier == "BELLE2018" ) FormFactor = sqrt( BlattWeisskopf_Norm( q2 * radius * radius, q20 * radius * radius, Lp ) ); if( L != 0 ){ diff --git a/src/Minimiser.cpp b/src/Minimiser.cpp index af5a6c4c6e2..136c71c8d72 100644 --- a/src/Minimiser.cpp +++ b/src/Minimiser.cpp @@ -23,12 +23,6 @@ using namespace ROOT; unsigned int Minimiser::nPars() const { return m_nParams; } -void Minimiser::print( const double& LL ) -{ - INFO( "Iteration # " << m_lastPrint << " FCN = " << round( LL, 3 ) << " Edm = " << round( m_minimiser->Edm(), 3 ) - << " NCalls = " << m_minimiser->NCalls() ); -} - double Minimiser::operator()( const double* xx ) { for(size_t i = 0; i < m_mapping.size(); ++i ) { @@ -41,24 +35,6 @@ double Minimiser::operator()( const double* xx ) return LL - m_ll_zero; } -void Minimiser::GradientTest() -{ - for (size_t i = 0; i < m_mapping.size(); ++i) { - auto parameter = m_parSet->at( m_mapping[i] ); - double m = parameter->mean(); - parameter->setCurrentFitVal( parameter->meanInit() + parameter->stepInit() ); - double vp = FCN(); - parameter->setCurrentFitVal( parameter->meanInit() - parameter->stepInit() ); - double vm = FCN(); - if ( parameter->stepInit() == 0 ) { - WARNING( "Step of free parameter: " << parameter->name() << " = 0" ); - } else { - INFO( " dF/d{" << parameter->name() << "} = " << ( vp - vm ) / ( 2 * parameter->stepInit() ) ); - } - parameter->setCurrentFitVal( m ); - } -} - double Minimiser::FCN() const { return m_theFunction(); } void Minimiser::prepare() @@ -80,18 +56,12 @@ void Minimiser::prepare() for(size_t i = 0 ; i < m_parSet->size(); ++i) { auto par = m_parSet->at(i); - if ( par->iFixInit() != 0 ) continue; + if ( ! par->isFree() ) continue; m_minimiser->SetVariable(m_mapping.size(), par->name(), par->mean(), par->stepInit()); if ( par->minInit() != 0 || par->maxInit() != 0 ) m_minimiser->SetVariableLimits( m_mapping.size(), par->minInit(), par->maxInit() ); m_mapping.push_back(i); - if ( m_printLevel != 0 ) { - INFO( "Parameter: " << std::left << std::setw(60) << par->name() << " = " - << std::right << std::setw(12) << par->mean() << " ± " - << std::left << std::setw(12) << par->stepInit() - << ( ( par->minInit() != 0 || par->maxInit() != 0 ) ? - ("["+ std::to_string(par->minInit()) + ", " + std::to_string(par->maxInit() ) ) + "]" : "" ) ); - } + if ( m_printLevel != 0 ) INFO( *par ); } m_nParams = m_mapping.size(); m_covMatrix.resize( m_nParams * m_nParams, 0 ); @@ -116,10 +86,6 @@ bool Minimiser::doFit() for ( unsigned int j = 0; j < m_nParams; ++j ) { m_covMatrix[i + m_nParams * j] = m_minimiser->CovMatrix( i, j ); } -// double up, down; -// double v = *(m_minimiser->X() +i); -// m_minimiser->GetMinosError(i, up, down); -// INFO( par->name() << " " << v << " " << par->mean() << " " << up << " " << down << " " << error ); } m_status = m_minimiser->Status(); return 1; diff --git a/src/MinuitParameter.cpp b/src/MinuitParameter.cpp index bf51b7509f1..f61202f17f5 100644 --- a/src/MinuitParameter.cpp +++ b/src/MinuitParameter.cpp @@ -8,23 +8,22 @@ using namespace AmpGen; -MinuitParameter::MinuitParameter( const std::string& name, const MinuitParameter::Flag& fix, const double& mean, const double& step, +MinuitParameter::MinuitParameter( const std::string& name, const Flag& fix, const double& mean, const double& step, const double& mi, const double& ma ) - : m_iFixInit( fix ), m_name( name ), m_meanInit( mean ), m_stepInit( step ), m_minInit( mi ), m_maxInit( ma ) + : m_flag( fix ), m_name( name ), m_meanInit( mean ), m_stepInit( step ), m_minInit( mi ), m_maxInit( ma ) { DEBUG( "Building parameter : " << name ); resetToInit(); } MinuitParameter::MinuitParameter( const std::string& name, const double& mean, const double& step, const double& mi, const double& ma ) - : MinuitParameter(name, MinuitParameter::Flag::Float, m_meanInit, m_stepInit, m_minInit, m_maxInit ) + : MinuitParameter(name, Flag::Free, m_meanInit, m_stepInit, m_minInit, m_maxInit ) { DEBUG( "Building parameter : " << name ); resetToInit(); } -MinuitParameter::Flag MinuitParameter::iFixInit() const { return m_iFixInit; } - +Flag MinuitParameter::flag() const { return m_flag; } double MinuitParameter::meanInit() const { return m_meanInit; } double MinuitParameter::stepInit() const { return m_stepInit; } double MinuitParameter::minInit() const { return m_minInit; } @@ -33,10 +32,11 @@ double MinuitParameter::mean() const { return m_meanResult; } double MinuitParameter::errPos() const { return m_errPosResult; } double MinuitParameter::errNeg() const { return m_errNegResult; } double MinuitParameter::err() const { return m_errResult; } +bool MinuitParameter::isFixed() const { return m_flag == Flag::Fix || m_flag == Flag::CompileTimeConstant; } +bool MinuitParameter::isFree() const { return m_flag == Flag::Free; } +const std::string& MinuitParameter::name() const { return m_name; } -bool MinuitParameter::fixed() { return m_iFixInit == Flag::Fix; } - -void MinuitParameter::fix() { m_iFixInit = Flag::Fix; } +void MinuitParameter::fix() { m_flag = Flag::Fix; } void MinuitParameter::scaleStep( const double& sf ) { m_errResult *= sf; @@ -47,10 +47,8 @@ void MinuitParameter::setStepInit( const double& si ) m_stepInit = si; } -const std::string& MinuitParameter::name() const { return m_name; } -bool MinuitParameter::hidden() const { return m_iFixInit == 1; } -void MinuitParameter::setFree() { INFO("Setting parameter: " << m_name << " free" ) ; m_iFixInit = Flag::Float; } +void MinuitParameter::setFree() { INFO("Setting parameter: " << m_name << " free" ) ; m_flag = Flag::Free; } void MinuitParameter::setCurrentFitVal( double cfv ) { m_meanResult = cfv; } @@ -64,11 +62,6 @@ void MinuitParameter::setResult( double fitMean, double fitErr, double fitErrPos m_errNegResult = fitErrNeg; } -void MinuitParameter::print( std::ostream& os ) const -{ - os << std::left << std::setw(65) << name() << "\t" << iFixInit() << "\t" << mean() << "\t" << err() << "\t" << minInit() << "\t" << maxInit(); -} - void MinuitParameter::setName( const std::string& name ) { m_name = name; } void MinuitParameter::resetToInit() @@ -84,3 +77,12 @@ void MinuitParameter::setLimits( const double& min, const double& max ) m_minInit = min; m_maxInit = max; } + +std::ostream& AmpGen::operator<<( std::ostream& os, const MinuitParameter& par ){ + return os << std::left << std::setw(60) << par.name() << " = " + << std::right << std::setw(12) << par.mean() << " ± " + << std::left << std::setw(12) << par.stepInit() + << ( ( par.minInit() != 0 || par.maxInit() != 0 ) ? + ("["+ std::to_string(par.minInit()) + ", " + std::to_string(par.maxInit() ) ) + "]" : "") + << " [flag=" << to_string(par.flag()) << "]"; +} diff --git a/src/MinuitParameterSet.cpp b/src/MinuitParameterSet.cpp index 6615b7b23f7..367185d5917 100644 --- a/src/MinuitParameterSet.cpp +++ b/src/MinuitParameterSet.cpp @@ -25,6 +25,7 @@ MinuitParameterSet::MinuitParameterSet(const std::vector& para { for( auto& param : params ) add(param); } + MinuitParameterSet::MinuitParameterSet( const MinuitParameterSet& other ) : m_parameters( other.m_parameters ), m_keyAccess( other.m_keyAccess ){} @@ -32,9 +33,8 @@ MinuitParameterSet MinuitParameterSet::getFloating() { MinuitParameterSet floating; for ( auto& param : *this ) { - if ( param->iFixInit() == MinuitParameter::Flag::Float && - dynamic_cast(param) != nullptr - ) floating.add(param); + if ( param->isFree() && dynamic_cast(param) != nullptr ) + floating.add(param); } return floating; } @@ -54,7 +54,7 @@ bool MinuitParameterSet::addToEnd( MinuitParameter* parPtr ) MinuitParameter* MinuitParameterSet::add( const std::string& name, const unsigned int& flag, const double& mean, const double& sigma, const double& min, const double& max ) { - addToEnd( new MinuitParameter( name, MinuitParameter::Flag(flag), mean, sigma, min, max ) ); + addToEnd( new MinuitParameter( name, Flag(flag), mean, sigma, min, max ) ); return m_keyAccess[name]; } @@ -75,17 +75,15 @@ unsigned int MinuitParameterSet::size() const { return m_parameters.size(); } void MinuitParameterSet::print( std::ostream& os ) const { for (size_t i = 0; i < size(); i++ ) { - os << '\n'; - m_parameters[i]->print(os); + os << '\n' << *m_parameters[i]; } os << '\n'; } void MinuitParameterSet::printVariable( std::ostream& os ) const { for (size_t i = 0; i < size(); i++ ) { - if ( m_parameters[i]->iFixInit() == 1 ) continue; /// hide parameter - os << '\n'; - m_parameters[i]->print( os ); + if ( m_parameters[i]->flag() == Flag::Hide ) continue; /// hide parameter + os << '\n' << *m_parameters[i]; } } @@ -128,63 +126,39 @@ MinuitParameter* MinuitParameterSet::at( const size_t& index ) const void MinuitParameterSet::tryParameter( const std::vector& line ) { + bool status = true; if ( line.size() == 4 || line.size() == 6 ) { - bool status = true; - int flag = lexical_cast( line[1], status ); - if( flag > 3 ) return ; + bool hasLimits = line.size() == 6; double mean = lexical_cast( line[2], status ); double step = lexical_cast( line[3], status ); - double min = line.size() == 6 ? lexical_cast( line[4], status ) : 0; - double max = line.size() == 6 ? lexical_cast( line[5], status ) : 0; - - if ( status ) { - if ( OptionsParser::printHelp() ) - INFO( "MINUIT: Registered " << line[0] << " (flag " << flag << ") = " << mean << ", step=" << step << " (" - << min << "," << max << ")" ); - add( new MinuitParameter( line[0], MinuitParameter::Flag(flag), mean, step, min, max ) ); - } - return; + double min = hasLimits ? lexical_cast( line[4], status ) : 0; + double max = hasLimits ? lexical_cast( line[5], status ) : 0; + if( !status ) return; + auto flag = parse( line[1] ); + if ( OptionsParser::printHelp() ) + INFO( "MINUIT: Registered " << line[0] << " (flag " << flag << ") = " << mean << ", step=" << step << " ("<< min << "," << max << ")" ); + add( new MinuitParameter( line[0], flag, mean, step, min, max ) ); } - if ( line.size() == 7 ) { - - bool status = true; - int flag_re = lexical_cast( line[1], status ); + if ( line.size() == 7 || line.size() == 11 ) { + bool hasLimits = line.size() == 11; double mean_re = lexical_cast( line[2], status ); double step_re = lexical_cast( line[3], status ); - int flag_im = lexical_cast( line[4], status ); - double mean_im = lexical_cast( line[5], status ); - double step_im = lexical_cast( line[6], status ); + double min_re = hasLimits ? lexical_cast( line[4], status ) : 0; + double max_re = hasLimits ? lexical_cast( line[5], status ) : 0; + double mean_im = lexical_cast( line[5 + 2 *hasLimits], status ); + double step_im = lexical_cast( line[6 + 2 *hasLimits], status ); + double min_im = hasLimits ? lexical_cast( line[9] , status ) : 0; + double max_im = hasLimits ? lexical_cast( line[10], status ) : 0; - double min_re = 0; - double max_re = 0; - double min_im = 0; - double max_im = 0; if ( !status ) return; + auto flag_re = parse(line[1]); + auto flag_im = parse(line[4 + 2*hasLimits]); if ( OptionsParser::printHelp() ) { - INFO( "MINUIT: Complex " << line[0] << "_Re (flag " << flag_re << ") = " << mean_re << ", step=" << step_re - << " (" << min_re << "," << max_re << ")" ); - INFO( "MINUIT: Complex " << line[0] << "_Im (flag " << flag_im << ") = " << mean_im << ", step=" << step_im - << " (" << min_im << "," << max_im << ")" ); + INFO( "MINUIT: Complex " << line[0] << "_Re (flag " << flag_re << ") = " << mean_re << ", step=" << step_re << " (" << min_re << "," << max_re << ")" ); + INFO( "MINUIT: Complex " << line[0] << "_Im (flag " << flag_im << ") = " << mean_im << ", step=" << step_im << " (" << min_im << "," << max_im << ")" ); } - add( new MinuitParameter( line[0] + "_Re", MinuitParameter::Flag(flag_re), mean_re, step_re, min_re, max_re ) ); - add( new MinuitParameter( line[0] + "_Im", MinuitParameter::Flag(flag_im), mean_im, step_im, min_im, max_im ) ); - } - if ( line.size() == 11 ) { - - bool status = true; - int flag_re = lexical_cast( line[1], status ); - double mean_re = lexical_cast( line[2], status ); - double step_re = lexical_cast( line[3], status ); - double min_re = lexical_cast( line[4], status ); - double max_re = lexical_cast( line[5], status ); - int flag_im = lexical_cast( line[6], status ); - double mean_im = lexical_cast( line[7], status ); - double step_im = lexical_cast( line[8], status ); - double min_im = lexical_cast( line[9], status ); - double max_im = lexical_cast( line[10], status ); - if ( !status ) return; - add( new MinuitParameter( line[0] + "_Re", MinuitParameter::Flag(flag_re), mean_re, step_re, min_re, max_re ) ); - add( new MinuitParameter( line[0] + "_Im", MinuitParameter::Flag(flag_im), mean_im, step_im, min_im, max_im ) ); + add( new MinuitParameter( line[0] + "_Re", flag_re, mean_re, step_re, min_re, max_re ) ); + add( new MinuitParameter( line[0] + "_Im", flag_im, mean_im, step_im, min_im, max_im ) ); } } diff --git a/src/Spline.cpp b/src/Spline.cpp index fbb9aa01ef7..7fb7a6bc207 100644 --- a/src/Spline.cpp +++ b/src/Spline.cpp @@ -123,7 +123,7 @@ void SplineTransfer::set( const unsigned int& N, MinuitParameter* f ) } void SplineTransfer::set( const unsigned int& N, const double& value ) { - m_parameters[N] = new MinuitParameter("dumb",MinuitParameter::Fix,value,0); + m_parameters[N] = new MinuitParameter("dumb", Flag::Fix, value, 0); } void SplineTransfer::transfer( CompiledExpressionBase* destination ) diff --git a/src/Wigner.cpp b/src/Wigner.cpp index ddca29c3711..14ec302740c 100644 --- a/src/Wigner.cpp +++ b/src/Wigner.cpp @@ -138,7 +138,7 @@ Expression AmpGen::wigner_D(const Tensor& P, db->emplace_back("pt2", pt2 ); db->emplace_back("p2" , sqrt( P[0]*P[0] + P[1] * P[1] + P[2]*P[2] ) ); db->emplace_back("ϕ("+name+")", atan2( py, px ) ); - db->emplace_back("θ("+name+")", pz ); + db->emplace_back("θ("+name+")", acos(pz) ); db->emplace_back("d[" + std::to_string(J) +", " + std::to_string(lA) +", " + std::to_string(lB) +"](θ)", little_d ); @@ -230,13 +230,16 @@ Expression AmpGen::helicityAmplitude(const Particle& particle, if( particle.props()->twoSpin() == 0 ) return Mz==0; // a scalar // polarisation spinor / vector etc. in the quantisation of the lab (i.e. along the z-axis or lab particle momentum) auto labPol = particle.externalSpinTensor(particle.polState(), db); - ADD_DEBUG_TENSOR(labPol, db); + //ADD_DEBUG_TENSOR(labPol, db); auto inverseMyTransform = myFrame.inverse(); if( particle.props()->twoSpin() == 1 ) // so a fermion { + if( NamedParameter("helicityAmplitude::NoSpinAlign", false ) ) return 2*Mz == particle.polState(); auto basisSpinor_m1 = basisSpinor( 2*Mz, particle.props()->pdgID() ); auto labSpinor_m1 = inverseMyTransform( basisSpinor_m1, Transform::Representation::Bispinor ); - ADD_DEBUG_TENSOR(labSpinor_m1, db); + //ADD_DEBUG_TENSOR(labSpinor_m1, db); + // lets just get the diagonal part // + ADD_DEBUG(Bar(labSpinor_m1)(a)*labPol(a), db ); return make_cse( Bar(labSpinor_m1)(a)*labPol(a) ); } if( particle.props()->twoSpin() == 2 ) // so a spin-one boson @@ -244,7 +247,7 @@ Expression AmpGen::helicityAmplitude(const Particle& particle, auto frameVector = basisVector(Mz); auto labVector = inverseMyTransform( frameVector, Transform::Representation::Vector ); auto rp = dot( labVector.conjugate(), labPol ); - ADD_DEBUG_TENSOR(labVector, db); + //ADD_DEBUG_TENSOR(labVector, db); ADD_DEBUG(rp, db ); return rp; } diff --git a/test/test_AmplitudeRules.cpp b/test/test_AmplitudeRules.cpp index 1a039af09d6..eac040ba354 100644 --- a/test/test_AmplitudeRules.cpp +++ b/test/test_AmplitudeRules.cpp @@ -13,8 +13,8 @@ using namespace AmpGen; BOOST_AUTO_TEST_CASE( test_AmplitudeRule ) { - MinuitParameter re = MinuitParameter("D0{K*(892)bar0{K-,pi+},pi0}_Re",MinuitParameter::Flag::Float,1.,0.); - MinuitParameter im = MinuitParameter("D0{K*(892)bar0{K-,pi+},pi0}_Im",MinuitParameter::Flag::Float,0.,0.); + MinuitParameter re = MinuitParameter("D0{K*(892)bar0{K-,pi+},pi0}_Re", Flag::Free,1.,0.); + MinuitParameter im = MinuitParameter("D0{K*(892)bar0{K-,pi+},pi0}_Im", Flag::Free,0.,0.); AmplitudeRule test(&re,&im); @@ -25,14 +25,14 @@ BOOST_AUTO_TEST_CASE( test_AmplitudeRule ) { } AmplitudeRules rule_set( MinuitParameterSet( { - new MinuitParameter("D0{K*(892)bar0,pi0}_Re", MinuitParameter::Flag::Fix,1.,0.) - , new MinuitParameter("D0{K*(892)bar0,pi0}_Im", MinuitParameter::Flag::Fix,1.,0.) - , new MinuitParameter("D0{rho(770)+,pi-}_Re" , MinuitParameter::Flag::Fix,1.,0.) - , new MinuitParameter("D0{rho(770)+,pi-}_Im" , MinuitParameter::Flag::Fix,2.,0.) - , new MinuitParameter("K*(892)bar0{K-,pi+}_Re", MinuitParameter::Flag::Float,sqrt(1./3.),0.) - , new MinuitParameter("K*(892)bar0{K-,pi+}_Im", MinuitParameter::Flag::Float,0,0.) - , new MinuitParameter("K*(892)bar0{K0,pi0}_Re", MinuitParameter::Flag::Fix,sqrt(2./3.),0.) - , new MinuitParameter("K*(892)bar0{K0,pi0}_Im", MinuitParameter::Flag::Fix,0,0.) } ) ); + new MinuitParameter("D0{K*(892)bar0,pi0}_Re", Flag::Fix,1.,0.) + , new MinuitParameter("D0{K*(892)bar0,pi0}_Im", Flag::Fix,1.,0.) + , new MinuitParameter("D0{rho(770)+,pi-}_Re" , Flag::Fix,1.,0.) + , new MinuitParameter("D0{rho(770)+,pi-}_Im" , Flag::Fix,2.,0.) + , new MinuitParameter("K*(892)bar0{K-,pi+}_Re", Flag::Free,sqrt(1./3.),0.) + , new MinuitParameter("K*(892)bar0{K-,pi+}_Im", Flag::Free,0,0.) + , new MinuitParameter("K*(892)bar0{K0,pi0}_Re", Flag::Fix,sqrt(2./3.),0.) + , new MinuitParameter("K*(892)bar0{K0,pi0}_Im", Flag::Fix,0,0.) } ) ); BOOST_AUTO_TEST_CASE( test_AmplitudeRules_constructor ){ BOOST_CHECK( rule_set.rules().size() == 2 ); /// number of head decays diff --git a/test/test_ExpressionParser.cpp b/test/test_ExpressionParser.cpp index de05c5a99a5..f2822eebbf7 100644 --- a/test/test_ExpressionParser.cpp +++ b/test/test_ExpressionParser.cpp @@ -30,11 +30,11 @@ BOOST_AUTO_TEST_CASE( parametericExpressions ) { double f = 3.13; MinuitParameterSet mps( { - new MinuitParameter("a", MinuitParameter::Flag::Float, a, 0.) - , new MinuitParameter("b", MinuitParameter::Flag::Float, b, 0.) - , new MinuitParameter("c", MinuitParameter::Flag::Float, c, 0.) - , new MinuitParameter("d", MinuitParameter::Flag::Float, d, 0.) - , new MinuitParameter("f", MinuitParameter::Flag::Float, f, 0.) + new MinuitParameter("a", Flag::Free, a, 0.) + , new MinuitParameter("b", Flag::Free, b, 0.) + , new MinuitParameter("c", Flag::Free, c, 0.) + , new MinuitParameter("d", Flag::Free, d, 0.) + , new MinuitParameter("f", Flag::Free, f, 0.) }); double pi = M_PI; From d2d0e3b5297e096f4c4ca1ec6f3bdf23774d5422 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 13 Aug 2019 17:40:04 +0200 Subject: [PATCH 085/250] Add release notes --- doc/release.notes | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/release.notes b/doc/release.notes index 9f0c70a4fbd..73ce7baa822 100644 --- a/doc/release.notes +++ b/doc/release.notes @@ -3,7 +3,8 @@ ! Responsible : Tim Evans ! Purpose : !----------------------------------------------------------------------------- -!=================== AmpGen v1r2 2019-05-29 ================== +!=================== AmpGen v1r2 2019-08-13 ================== + - Tagged to match results in Gauss/LbAmpGen v49r14+ - Improved thread support for CoherentSum - Add examples/QcGenerator for Ψ(3770) decays ! 2019-05-29 - Tim Evans From f23dd6b49da65c6535d542407ba94a579124058c Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 13 Aug 2019 22:42:00 +0200 Subject: [PATCH 086/250] fix SFINAE snafu --- AmpGen/EventList.h | 9 ++++++--- AmpGen/MetaUtils.h | 13 +++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index a0b58fdbb33..4303467c94d 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -7,6 +7,7 @@ #include "AmpGen/Event.h" #include "AmpGen/Projection.h" #include "AmpGen/Utilities.h" +#include "AmpGen/MetaUtils.h" #include #include @@ -140,18 +141,20 @@ namespace AmpGen return makeProjections( proj , argPack ); } - template std::vector makeProjections( const std::vector& projections, const ARGS&... args ) + template std::vector makeProjections( const std::vector& projections, const ARGS&... args ) { return makeProjections( projections, ArgumentPack( args... ) ); } - template ::type, ArgumentPack> = 0 > + template , ArgumentPack>::value > > TH1D* makeProjection( const Projection& projection, const ARGS&... args ) const { return makeProjection( projection, ArgumentPack(args...) ); } - template ::type, ArgumentPack> = 0 > + template , ArgumentPack>::value > > TH2D* makeProjection( const Projection2D& projection, const ARGS&... args ) { return makeProjection( projection, ArgumentPack(args...) ); diff --git a/AmpGen/MetaUtils.h b/AmpGen/MetaUtils.h index 8f83aace4f7..138e8358d81 100644 --- a/AmpGen/MetaUtils.h +++ b/AmpGen/MetaUtils.h @@ -26,14 +26,19 @@ namespace AmpGen template std::string typeof( TYPE t ) { return typeof(); } - template struct zeroType { typedef T type; }; - + namespace detail { + template struct zeroType { typedef T type; }; + } + template using nthType = typename std::tuple_element>::type; + + template using zeroType = typename detail::zeroType::type; + template - typename std::enable_if::type + typename std::enable_if_t for_each( std::tuple&, FuncT ){} template - inline typename std::enable_if < I::type for_each( std::tuple& t, FuncT f ) + inline typename std::enable_if_t< I for_each( std::tuple& t, FuncT f ) { f( std::get( t ) ); for_each( t, f ); From 0d4045cc27ed622d0818898e03f90a841129b014 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 22 Aug 2019 22:02:08 +0200 Subject: [PATCH 087/250] Add faster integrator , improvements in documentation and additional flags for Gounaris Sakurai lineshape --- AmpGen/AmplitudeRules.h | 12 +- AmpGen/CoherentSum.h | 13 +- AmpGen/EventList.h | 1 + AmpGen/EventType.h | 1 - AmpGen/Generator.h | 258 ++++++++++++++-------------- AmpGen/IncoherentSum.h | 11 +- AmpGen/Integrator.h | 23 +-- AmpGen/Integrator2.h | 124 +++++++++++++ AmpGen/MetaUtils.h | 13 +- AmpGen/MsgService.h | 16 +- AmpGen/NamedParameter.h | 36 ++-- AmpGen/Pade.h | 88 +++++----- AmpGen/Particle.h | 92 +++++----- AmpGen/ParticleProperties.h | 162 ++++++++--------- AmpGen/PhaseSpace.h | 46 +++-- AmpGen/Plots.h | 4 +- AmpGen/PolarisedSum.h | 8 +- AmpGen/SimPDF.h | 32 ++-- AmpGen/SumPDF.h | 87 +++++++--- apps/ConvertToSourceCode.cpp | 4 +- apps/Debugger.cpp | 2 +- apps/Fitter.cpp | 6 +- examples/FitterWithPolarisation.cpp | 3 +- examples/SignalOnlyFitter.cpp | 38 ++-- examples/SimFit.cpp | 11 +- src/CoherentSum.cpp | 60 +++---- src/EventType.cpp | 17 +- src/IncoherentSum.cpp | 18 +- src/Lineshapes/GounarisSakurai.cpp | 8 +- src/Pade.cpp | 30 ++++ src/Particle.cpp | 10 +- src/ParticleProperties.cpp | 68 +++----- src/PhaseSpace.cpp | 8 +- src/Plots.cpp | 8 +- src/PolarisedSum.cpp | 30 ++-- 35 files changed, 770 insertions(+), 578 deletions(-) create mode 100644 AmpGen/Integrator2.h create mode 100644 src/Pade.cpp diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index 235a56d3e58..68ce3866222 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -80,10 +80,10 @@ namespace AmpGen TransitionMatrix() = default; TransitionMatrix(const Particle& dt, const CouplingConstant& coupling, - const CompiledExpression & pdf) : + const CompiledExpression & amp) : decayTree(dt), coupling(coupling), - pdf(pdf) {} + amp(amp) {} TransitionMatrix(Particle& dt, const CouplingConstant& coupling, @@ -95,18 +95,18 @@ namespace AmpGen { DebugSymbols db; auto expression = dt.getExpression(debugThis ? &db : nullptr); - pdf = CompiledExpression + amp = CompiledExpression (expression, dt.decayDescriptor(), evtFormat, debugThis ? db : DebugSymbols(), &mps ); } - const RT operator()(const Event& event) const { return pdf(event.address() ); } - const RT operator()(const Event& event, const size_t& cacheOffset) const { return pdf(event.address() + cacheOffset); } + const RT operator()(const Event& event) const { return amp(event.address() ); } + const RT operator()(const Event& event, const size_t& cacheOffset) const { return amp(event.address() + cacheOffset); } const std::string decayDescriptor() const { return decayTree.decayDescriptor() ; } Particle decayTree; CouplingConstant coupling; complex_t coefficient; - CompiledExpression pdf; + CompiledExpression amp; size_t addressData = {999}; }; diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index a3048971f4e..ead5946fd55 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -15,8 +15,10 @@ #include "AmpGen/EventList.h" #include "AmpGen/EventType.h" #include "AmpGen/Integrator.h" +#include "AmpGen/Integrator2.h" #include "AmpGen/Types.h" #include "AmpGen/Event.h" +#include "AmpGen/Projection.h" namespace AmpGen { @@ -52,9 +54,9 @@ namespace AmpGen size_t size() const { return m_matrixElements.size(); } real_t getWeight() const { return m_weight; } - real_t operator()( const Event& evt ) const { return prob( evt ); } - real_t prob( const Event& evt ) const { return m_weight * std::norm( getVal( evt ) ) / m_norm; } - real_t prob_unnormalised( const Event& evt ) const { return std::norm( getVal( evt ) ); } + real_t operator()( const Event& evt ) const { return m_weight*std::norm(getVal(evt))/m_norm; } + real_t prob( const Event& evt ) const { return m_weight*std::norm(getVal(evt))/m_norm; } + real_t prob_unnormalised( const Event& evt ) const { return std::norm(getVal(evt)); } real_t norm( const Bilinears& norms ) const; real_t norm() const; real_t getNorm( const Bilinears& normalisations ); @@ -84,12 +86,13 @@ namespace AmpGen std::map> getGroupedAmplitudes(); Bilinears norms() const { return m_normalisations ; } - + protected: + typedef Integrator<10> integrator; std::vector> m_matrixElements; ///< Vector of (expanded) matrix elements Bilinears m_normalisations; ///< Normalisation integrals AmplitudeRules m_protoAmplitudes; ///< Proto amplitudes from user rule-set - Integrator<10> m_integrator; ///< Integral dispatch tool (with default unroll = 10) + integrator m_integrator; ///< Integral dispatch tool (with default unroll = 10) TransitionMatrix m_total; ///< Total Matrix Element EventList* m_events = {nullptr}; ///< Data events to evaluate PDF on EventType m_evtType; ///< Final state for this amplitude diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 4303467c94d..709fd40eaa6 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -39,6 +39,7 @@ namespace AmpGen double m_norm = {0}; size_t m_lastCachePosition = {0}; public: + typedef Event value_type; EventList() = default; EventList( const EventType& type ); template < class ... ARGS > EventList( const std::string& fname, const EventType& evtType, const ARGS&... args ) : EventList(evtType) diff --git a/AmpGen/EventType.h b/AmpGen/EventType.h index 19c05ee53a1..d7b8fd04606 100644 --- a/AmpGen/EventType.h +++ b/AmpGen/EventType.h @@ -37,7 +37,6 @@ namespace AmpGen /// the same name as the index'th name. std::pair count(const size_t& index) const; std::pair minmax( const std::vector& indices, bool isGeV = false ) const; - std::vector> getBosePairs() const; std::vector masses() const; std::string mother() const; double mass( const size_t& index ) const; diff --git a/AmpGen/Generator.h b/AmpGen/Generator.h index b338c41bf92..8b258e044be 100644 --- a/AmpGen/Generator.h +++ b/AmpGen/Generator.h @@ -10,143 +10,149 @@ namespace AmpGen { template - class Generator - { - private: - EventType m_eventType; - PHASESPACE m_gps; - size_t m_generatorBlock = {5000000}; - TRandom* m_rnd = {gRandom}; - bool m_normalise = {true}; - - public: - template - Generator( const ARGS&... args ) - : m_gps(args...) - { - m_eventType = m_gps.eventType(); - setRandom( m_rnd ); - } - PHASESPACE phsp() { return m_gps; } - void setRandom( TRandom* rand ) - { - m_rnd = rand; - m_gps.setRandom( m_rnd ); - } - void fillEventListPhaseSpace( EventList& list, const size_t& N, const size_t& cacheSize = 0 ) + class Generator { - fillEventListPhaseSpace( list, N, cacheSize, []( const Event& evt ) { return 1; } ); - } - void setBlockSize( const size_t& blockSize ) { m_generatorBlock = blockSize; } - void setNormFlag( const bool& normSetting ) { m_normalise = normSetting; } + private: + EventType m_eventType; + PHASESPACE m_gps; + size_t m_generatorBlock = {5000000}; + TRandom* m_rnd = {gRandom}; + bool m_normalise = {true}; - template void fillEventListPhaseSpace( EventList& list, const size_t& N, const size_t& cacheSize, HARD_CUT cut ) - { - list.reserve( N ); - while( list.size() < N ){ - Event newEvent = m_gps.makeEvent( cacheSize ); - newEvent.setWeight( 1 ); - if ( cut( newEvent ) ) list.push_back( newEvent ); - } - } - - template - void fillEventList( PDF& pdf, EventList& list, const size_t& N ) - { - fillEventList( pdf, list, N, []( const Event& /*evt*/ ) { return 1; } ); - } - - template - void fillEventList( PDF& pdf, EventList& list, const size_t& N, HARD_CUT cut ) - { - if ( m_rnd == nullptr ) { - ERROR( "Random generator not set!" ); - return; - } - double normalisationConstant = m_normalise ? 0 : 1; - auto size0 = list.size(); - auto tStartTotal = std::chrono::high_resolution_clock::now(); - pdf.reset( true ); - ProgressBar pb(60, trimmedString(__PRETTY_FUNCTION__) ); - ProfileClock t_phsp, t_eval, t_acceptReject; - while ( list.size() - size0 < N ) { - EventList mc( m_eventType ); - t_phsp.start(); - fillEventListPhaseSpace( mc, m_generatorBlock, pdf.size(), cut ); - t_phsp.stop(); - t_eval.start(); - pdf.setEvents( mc ); - pdf.prepare(); - t_eval.stop(); - if ( normalisationConstant == 0 ) { - double max = 0; - for ( auto& evt : mc ) { - double value = pdf.prob_unnormalised( evt ); - if ( value > max ) max = value; + public: + template + Generator( const ARGS&... args ) + : m_gps(args...) + { + m_eventType = m_gps.eventType(); + setRandom( m_rnd ); } - normalisationConstant = max * 1.5; - INFO( "Setting normalisation constant = " << normalisationConstant ); + PHASESPACE phsp() { return m_gps; } + void setRandom( TRandom* rand ) + { + m_rnd = rand; + m_gps.setRandom( m_rnd ); + } + void fillEventListPhaseSpace( EventList& list, const size_t& N, const size_t& cacheSize = 0 ) + { + fillEventListPhaseSpace( list, N, cacheSize, []( const Event& evt ) { return 1; } ); } - auto previousSize = list.size(); - t_acceptReject.start(); - #ifdef _OPENMP - #pragma omp parallel for - #endif - for ( size_t i=0;i< mc.size(); ++i ) mc[i].setGenPdf(pdf.prob_unnormalised(mc[i])); + void setBlockSize( const size_t& blockSize ) { m_generatorBlock = blockSize; } + void setNormFlag( const bool& normSetting ) { m_normalise = normSetting; } - for( auto& evt : mc ){ - if ( evt.genPdf() > normalisationConstant ) { - std::cout << std::endl; - WARNING( "PDF value exceeds norm value: " << evt.genPdf() << " > " << normalisationConstant ); + template void fillEventListPhaseSpace( EventList& list, const size_t& N, const size_t& cacheSize, HARD_CUT cut ) + { + list.reserve( N ); + while( list.size() < N ){ + Event newEvent = m_gps.makeEvent( cacheSize ); + newEvent.setWeight( 1 ); + if ( cut( newEvent ) ) list.push_back( newEvent ); } - if ( evt.genPdf() > normalisationConstant * m_rnd->Rndm() ) list.push_back( evt ); - if ( list.size() - size0 == N ) break; } - t_acceptReject.stop(); - double time = std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); - double efficiency = 100. * ( list.size() - previousSize ) / (double)m_generatorBlock; - pb.print( double(list.size()) / double(N), " ε[gen] = " + mysprintf("%.2f",efficiency) + "% , " + std::to_string(int(time/1000.)) + " seconds" ); - if ( list.size() == previousSize ) { - ERROR( "No events generated, PDF: " << typeof() << " is likely to be malformed" ); - break; + + template + void fillEventList( PDF& pdf, EventList& list, const size_t& N ) + { + fillEventList( pdf, list, N, []( const Event& /*evt*/ ) { return 1; } ); + } + + template + void fillEventList( PDF& pdf, EventList& list, const size_t& N, HARD_CUT cut ) + { + if ( m_rnd == nullptr ) { + ERROR( "Random generator not set!" ); + return; + } + double normalisationConstant = m_normalise ? 0 : 1; + auto size0 = list.size(); + auto tStartTotal = std::chrono::high_resolution_clock::now(); + pdf.reset( true ); + ProgressBar pb(60, trimmedString(__PRETTY_FUNCTION__) ); + ProfileClock t_phsp, t_eval, t_acceptReject; + while ( list.size() - size0 < N ) { + EventList mc( m_eventType ); + t_phsp.start(); + fillEventListPhaseSpace( mc, m_generatorBlock, pdf.size(), cut ); + t_phsp.stop(); + t_eval.start(); + pdf.setEvents( mc ); + pdf.prepare(); + t_eval.stop(); + if ( normalisationConstant == 0 ) { + double max = 0; + for ( auto& evt : mc ) { + double value = pdf.prob_unnormalised( evt ); + if ( value > max ) max = value; + } + normalisationConstant = max * 1.5; + INFO( "Setting normalisation constant = " << normalisationConstant ); + } + auto previousSize = list.size(); + t_acceptReject.start(); +#ifdef _OPENMP +#pragma omp parallel for +#endif + for ( size_t i=0;i< mc.size(); ++i ) mc[i].setGenPdf(pdf.prob_unnormalised(mc[i])); + + for( auto& evt : mc ){ + if ( evt.genPdf() > normalisationConstant ) { + std::cout << std::endl; + WARNING( "PDF value exceeds norm value: " << evt.genPdf() << " > " << normalisationConstant ); + } + if ( evt.genPdf() > normalisationConstant * m_rnd->Rndm() ) list.push_back( evt ); + if ( list.size() - size0 == N ) break; + } + t_acceptReject.stop(); + double time = std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); + double efficiency = 100. * ( list.size() - previousSize ) / (double)m_generatorBlock; + pb.print( double(list.size()) / double(N), " ε[gen] = " + mysprintf("%.2f",efficiency) + "% , " + std::to_string(int(time/1000.)) + " seconds" ); + if ( list.size() == previousSize ) { + ERROR( "No events generated, PDF: " << typeof() << " is likely to be malformed" ); + break; + } + } + pb.finish(); + double time = std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); + INFO( "Generated " << N << " events in " << time << " ms" ); + INFO( "Generating phase space : " << t_phsp << " ms"); + INFO( "Evaluating PDF : " << t_eval << " ms"); + INFO( "Doing accept/reject : " << t_acceptReject << " ms"); + } + template ::value>::type> + EventList generate(PDF& pdf, const size_t& nEvents ) + { + EventList evts( m_eventType ); + fillEventList( pdf, evts, nEvents ); + return evts; + } + EventList generate(const size_t& nEvents, const size_t& cacheSize=0) + { + EventList evts( m_eventType ); + fillEventListPhaseSpace( evts, nEvents, cacheSize ); + return evts; } - } - pb.finish(); - double time = std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); - INFO( "Generated " << N << " events in " << time << " ms" ); - INFO( "Generating phase space : " << t_phsp << " ms"); - INFO( "Evaluating PDF : " << t_eval << " ms"); - INFO( "Doing accept/reject : " << t_acceptReject << " ms"); - } - template ::value>::type> - EventList generate(PDF& pdf, const size_t& nEvents ) - { - EventList evts( m_eventType ); - fillEventList( pdf, evts, nEvents ); - return evts; - } - EventList generate(const size_t& nEvents, const size_t& cacheSize=0) - { - EventList evts( m_eventType ); - fillEventListPhaseSpace( evts, nEvents, cacheSize ); - return evts; - } - }; - template - class PDFWrapper { - FCN m_fcn; + }; + + template class PDFWrapper + { public: - void prepare(){}; - void setEvents( AmpGen::EventList& /*evts*/ ){}; - double prob_unnormalised( const AmpGen::Event& evt ) const { return m_fcn(evt); } - PDFWrapper( const FCN& fcn ) : m_fcn(fcn) {} - size_t size() const { return 0; } - void reset( const bool& /*flag*/ = false ){}; + void prepare(){}; + void setEvents( AmpGen::EventList& /*evts*/ ){}; + double prob_unnormalised( const AmpGen::Event& evt ) const { return m_fcn(evt); } + PDFWrapper( const FCN& fcn ) : m_fcn(fcn) {} + size_t size() const { return 0; } + void reset( const bool& /*flag*/ = false ){}; + + private: + FCN m_fcn; }; - + template PDFWrapper make_pdf(const FCN& fcn){ return PDFWrapper(fcn) ; } - + + /** @function PyGenerate + + Wrapper around the a phase space generator from a stringy event type to be used with python / numpy. + */ extern "C" void PyGenerate( const char* eventType, double* out, const unsigned int size ); } // namespace AmpGen #endif diff --git a/AmpGen/IncoherentSum.h b/AmpGen/IncoherentSum.h index 70479a3717c..589c6760057 100644 --- a/AmpGen/IncoherentSum.h +++ b/AmpGen/IncoherentSum.h @@ -42,20 +42,21 @@ namespace AmpGen IncoherentSum(const EventType& eventType, const AmpGen::MinuitParameterSet& mps, const std::string& prefix = "Inco"); /// Evaluates the normalised probability for an event. - double prob( const Event& evt ) const; - + real_t prob( const Event& evt ) const; + real_t operator()(const Event& evt) const { return prob(evt) ; } + /// Calculates the unnormalised probability for an event. - double prob_unnormalised( const Event& evt ) const; + real_t prob_unnormalised( const Event& evt ) const; /** Returns the normalisation for this PDF, given by @f[ \mathcal{N} = \int d\psi \varepsilon(\psi) \mathcal{P}(\psi) \approx \sum_i \frac{\mathcal{P}(\psi_i)}{\mathcal{P}^\prime(\psi_i)} @f] where the sum is over a simulated sample, generated with PDF @f$\mathcal{P}^\prime(\psi)@f$. */ - double norm() const; + real_t norm() const; complex_t norm(const size_t& i, const size_t& j){ return i==j ? m_normalisations.get(i, 0) : 0; } complex_t norm(const size_t& i) { return m_normalisations.get(i, 0); } - double norm( const Bilinears& norms ) const; + real_t norm( const Bilinears& norms ) const; std::vector fitFractions( const LinearErrorPropagator& linProp ); void prepare(); diff --git a/AmpGen/Integrator.h b/AmpGen/Integrator.h index 195fe075d04..eb8437ec05a 100644 --- a/AmpGen/Integrator.h +++ b/AmpGen/Integrator.h @@ -3,6 +3,7 @@ #include "AmpGen/Types.h" #include "AmpGen/EventList.h" +#include "AmpGen/CompiledExpressionBase.h" #include #include @@ -40,8 +41,7 @@ namespace AmpGen void resize(const size_t& r, const size_t& c = 1 ); }; - template - struct Integral { + template struct Integral { typedef std::function TransferFCN; size_t i = {0}; size_t j = {0}; @@ -82,6 +82,7 @@ namespace AmpGen for ( size_t j = 0; j < m_counter; ++j ) m_integrals[j].transfer( complex_t( re[j], im[j] ) / nv ); } + public: Integrator( EventList* events = nullptr ) : m_events( events ){} @@ -104,14 +105,13 @@ namespace AmpGen Bilinears* out, const bool& sim = true ) { - if( out->workToDo(i,j) ){ - if( sim ) - addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ - out->set(i,j,val); - if( i != j ) out->set(j,i, std::conj(val) ); } ); - else - addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ out->set(i,j,val); } ); - } + if( ! out->workToDo(i,j) )return; + if( sim ) + addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ + out->set(i,j,val); + if( i != j ) out->set(j,i, std::conj(val) ); } ); + else + addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ out->set(i,j,val); } ); } void addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ) { @@ -131,6 +131,9 @@ namespace AmpGen auto index = m_events->registerExpression( expression , size_of ); m_events->updateCache( expression, index ); } + size_t getCacheIndex(const CompiledExpressionBase& expression) const { + return m_events->getCacheIndex(expression); + } }; template diff --git a/AmpGen/Integrator2.h b/AmpGen/Integrator2.h new file mode 100644 index 00000000000..dd2900f654d --- /dev/null +++ b/AmpGen/Integrator2.h @@ -0,0 +1,124 @@ +#ifndef AMPGEN_INTEGRATOR2_H +#define AMPGEN_INTEGRATOR2_H 1 + +#include "AmpGen/Integrator.h" + +namespace AmpGen { + + template + class Integrator2 + { + private: + typedef const complex_t& arg; + typedef std::function TransferFCN; + size_t m_counter = {0}; + std::array, NROLL> m_integrals; + EventList* m_events = {nullptr}; + std::vector> m_buffer; + std::vector m_weight; + std::map m_index; + void integrateBlock() + { + real_t re[NROLL] = {0}; + real_t im[NROLL] = {0}; + size_t addr_i[NROLL] = {0}; + size_t addr_j[NROLL] = {0}; + for( size_t roll = 0 ; roll < NROLL; ++roll ) + { + addr_i[roll] = m_integrals[roll].i; + addr_j[roll] = m_integrals[roll].j; + } + #pragma omp parallel for reduction(+: re, im) + for ( size_t i = 0; i < m_events->size(); ++i ) { + for ( size_t roll = 0; roll < NROLL; ++roll ) { + auto c = m_buffer[addr_i[roll]][i] * std::conj(m_buffer[addr_j[roll]][i]); + re[roll] += m_weight[i] * std::real(c); + im[roll] += m_weight[i] * std::imag(c); + } + } + real_t nv = m_events->norm(); + for ( size_t j = 0; j < m_counter; ++j ) + m_integrals[j].transfer( complex_t( re[j], im[j] ) / nv ); + } + + public: + Integrator2( EventList* events = nullptr ) : m_events( events ){ + if( m_events != nullptr ){ + m_weight.resize( m_events->size() ); + for( size_t i = 0 ; i < m_events->size(); ++i ) + m_weight[i] = m_events->at(i).weight() / m_events->at(i).genPdf(); + } + } + + double sampleNorm() { return m_events->norm(); } + bool isReady() const { return m_events != nullptr; } + EventList& events() { return *m_events; } + const EventList& events() const { return *m_events; } + void queueIntegral(const size_t& c1, + const size_t& c2, + const size_t& i, + const size_t& j, + Bilinears* out, + const bool& sim = true) + { + if( ! out->workToDo(i,j) )return; + if( sim ) + addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ + out->set(i,j,val); + if( i != j ) out->set(j,i, std::conj(val) ); } ); + else + addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ out->set(i,j,val); } ); + } + void addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ) + { + m_integrals[m_counter++] = Integral(c1,c2,tFunc); + if ( m_counter == NROLL ){ integrateBlock(), m_counter = 0; } + } + void queueIntegral(const size_t& i, const size_t& j, complex_t* result){ + addIntegralKeyed(i, j, [result](arg& val){ *result = val ; } ); + } + void flush() + { + if ( m_counter == 0 ) return; + integrateBlock(); + m_counter =0; + } + template + size_t getCacheIndex(const EXPRESSION& expression) const { + return m_index.find(expression.name())->second; + } + template + void prepareExpression( const EXPRESSION& expression, const size_t& size_of = 0 ) + { + if( m_events == nullptr ) return; + size_t expression_size = size_of == 0 ? expression.returnTypeSize() / sizeof(complex_t) : size_of; + auto it = m_index.find( expression.name() ); + auto index = 0; + if( it == m_index.end() ) + { + index = m_buffer.size(); + m_index[ expression.name() ] = index; + m_buffer.resize(index+expression_size); + for(size_t j = 0 ; j != expression_size; ++j ) + m_buffer[index+j].resize( m_events->size() ); + } + else index = it->second; + #ifdef _OPENMP + #pragma omp parallel for + #endif + for ( size_t i = 0; i < m_events->size(); ++i ){ + auto v = expression(m_events->at(i).address()); + setBuffer( &(m_buffer[index][i]), v, expression_size ); + } + } + void setBuffer( complex_t* pos, const complex_t& value, const size_t& size ) + { + *pos = value; + } + void setBuffer( complex_t* pos, const std::vector& value, const size_t& size) + { + memcpy( pos, &(value[0]), size * sizeof(complex_t) ); + } + }; +} +#endif diff --git a/AmpGen/MetaUtils.h b/AmpGen/MetaUtils.h index 138e8358d81..4a74f1c089f 100644 --- a/AmpGen/MetaUtils.h +++ b/AmpGen/MetaUtils.h @@ -43,6 +43,18 @@ namespace AmpGen f( std::get( t ) ); for_each( t, f ); } + + template + typename std::enable_if_t + for_each( const std::tuple&, FuncT ){} + + template + inline typename std::enable_if_t< I for_each( const std::tuple& t, FuncT f ) + { + f( std::get( t ) ); + for_each( t, f ); + } + template std::shared_ptr makeShared( const TYPE& obj ) { @@ -90,7 +102,6 @@ namespace AmpGen } template struct isTuple: std::false_type {}; - template struct isTuple>: std::true_type {}; } // namespace AmpGen diff --git a/AmpGen/MsgService.h b/AmpGen/MsgService.h index 6e00b5d814e..775f4d297e6 100644 --- a/AmpGen/MsgService.h +++ b/AmpGen/MsgService.h @@ -1,9 +1,9 @@ #ifndef AMPGEN_MSGSERVICE_H #define AMPGEN_MSGSERVICE_H -/* +/** @defgroup msgService Messaging and logging MsgService Header - -Defines coloured and organised output macro streams using __PRETTY_FUNCTION__ + Defines coloured and organised output macro streams using __PRETTY_FUNCTION__ INFO() - info level messages, always displayed ERROR() - error level messages, always displayed FATAL() - error message that throws the process, always displayed @@ -43,7 +43,8 @@ inline std::string trimmedString( std::string thing, const unsigned int& length if ( thing.size() < length ) return thing; } - +/// @ingroup msgService macro DEBUG +/// Used for printing verbose debugging messages, only if DEBUGLEVEL is defined. #ifdef DEBUGLEVEL #define DEBUG( X ) \ std::cout << "\033[2;32m" << std::left << std::setw( FCNNAMELENGTH ) << trimmedString( __PRETTY_FUNCTION__ ) \ @@ -53,22 +54,31 @@ inline std::string trimmedString( std::string thing, const unsigned int& length #define DEBUG( X ) #endif +/// @ingroup msgService macro INFO +/// Used for printing information messages, and will always be printed. #define INFO( X ) \ std::cout << "\033[2;34m" << std::left << std::setw( FCNNAMELENGTH ) << trimmedString( __PRETTY_FUNCTION__ ) \ << " INFO " \ << "\033[0m" << X << std::endl +/// @ingroup msgService macro ERROR +/// Used for printing errors messages, and will always be printed. #define ERROR( X ) \ std::cout << "\033[1;31m" << std::left << std::setw( FCNNAMELENGTH ) << trimmedString( __PRETTY_FUNCTION__ ) \ << " ERROR " \ << "\033[0m" << X << std::endl +/// @ingroup msgService macro FATAL +/// Used for printing fatal errors messages, and will always be printed and will terminate the process afterwards. #define FATAL( X ) \ { std::cout << "\033[1;31m" << std::left << std::setw( FCNNAMELENGTH ) << trimmedString( __PRETTY_FUNCTION__ ) \ << " FATAL " \ << "\033[0m" << X << std::endl; \ throw std::runtime_error( trimmedString( __PRETTY_FUNCTION__)+ " FATAL" ) ;} + +/// @ingroup msgService macro FATAL +/// Used for printing warning messages, can be switched off using WARNINGLEVEL. These messages are often harmless, but sometimes not! #ifdef WARNINGLEVEL #define WARNING( X ) \ std::cout << "\033[1;35m" << std::left << std::setw( FCNNAMELENGTH ) << trimmedString( __PRETTY_FUNCTION__ ) \ diff --git a/AmpGen/NamedParameter.h b/AmpGen/NamedParameter.h index 18b993f5eb0..f0598abab89 100644 --- a/AmpGen/NamedParameter.h +++ b/AmpGen/NamedParameter.h @@ -20,13 +20,20 @@ namespace AmpGen { + /** @class NamedParameter + @brief A parameter with value specified by the user at runtime, either in an options file or via the command line + + Stores a vector of values for a parameter. + @tparam T the type of this named parameter, i.e. strings, or numbers or bools etc. + + */ template class NamedParameter { protected: - std::string m_name; - std::string m_helpString; - std::vector m_valueArray; + std::string m_name; /// < Name of this parameter + std::string m_helpString; /// < The helper string for this parameter, printed if the flag --help is used. + std::vector m_valueArray; /// < The value (array) of this parameter. bool setFromOptionsParser() { @@ -59,29 +66,6 @@ namespace AmpGen if ( OptionsParser::printHelp() ) help(def); DEBUG( *this ); } - /* - template - NamedParameter( const std::string& name, const T& def, const ARGS&... args ) : - m_name(name) - { - setVal( def ); - setFromOptionsParser(); - auto arg_pack = ArgumentPack(args...); - auto acceptedValues = arg_pack.getArg>().val; - m_helpString = arg_pack.getArg().val; - - if( acceptedValues.size() != 0 ){ - bool isAcceptedValue = false; - for( auto& v : acceptedValues ) if( m_valueArray[0] == v ) isAcceptedValue = true; - if( !isAcceptedValue ){ - ERROR( "Argument: " << name << " is not in [" << italic_on << vectorToString( acceptedValues, ", ") << italic_off <<"]" ); - } - } - if ( OptionsParser::printHelp() ) help(def); - DEBUG( *this ); - } - */ - NamedParameter(const std::string& name, const std::vector& defVec, const std::string& helpString="") : m_name(name), m_helpString(helpString) diff --git a/AmpGen/Pade.h b/AmpGen/Pade.h index 4e13fa9ca37..d18e69a681c 100644 --- a/AmpGen/Pade.h +++ b/AmpGen/Pade.h @@ -1,60 +1,54 @@ #ifndef AMPGEN_PADE_H #define AMPGEN_PADE_H -#include "TMatrixD.h" -#include "TVectorD.h" #include #include namespace AmpGen { enum Strategy { linear, quadratic, cubic, quartic }; - template - class Pade { - private: - std::function m_function; - std::array co_f; - std::array co_g; - T min; - T max; - T range; - public: + namespace detail { + std::vector solve_pade(const std::function& fcn, + const double& min, + const double& max, + const Strategy& strat = Strategy::linear); + } - Pade(const std::function& fcn, - const double& min, - const double& max, - const Strategy& strat = Strategy::linear) : - m_function(fcn), min(min),max(max){ - TMatrixD solver(2*N+1,2*N+1); - std::vector samples(2*N+1); - if( strat < 4 ){ - for(size_t eq = 0 ; eq < 2*N+1; ++eq) - samples[eq] = pow( eq/double(2*N), strat + 1); - } - TVectorD rest(2*N+1); - for( int eq = 0 ; eq < 2*N+1; ++eq ){ - rest(eq) = fcn( samples[eq]*(max-min) + min); - for(int i = 0; i <= N; ++i) solver(eq,i) = pow(samples[eq],i); - for(int i = 1; i <= N; ++i) solver(eq,i+N) = -rest(eq)* pow(samples[eq],i); - } - solver.Invert(); - auto r = solver * rest; - for(size_t i = 0; i <= N; ++i ) co_f[i] = r[i]; - for(size_t i = 0; i < N; ++i ) co_g[i] = r[i+(N+1)]; - range = 1./(max-min); - } - T operator()(const T& s){ - T x = (s-min)*range; - T f = 0; - T g = 1; - T acc = 1; - for(size_t i = 0; i < N; ++i){ - f += co_f[i] * acc; - acc *= x; - g += co_g[i] * acc; - } - return (f + co_f[N]*acc)/g; + template class Pade + { + public: + Pade(const std::function& fcn, + const double& min, + const double& max, + const Strategy& strat = Strategy::linear) : + m_function(fcn), min(min),max(max) + { + auto r = detail::solve_pade(fcn, min, max, N, strat ); + for(size_t i = 0; i <= N; ++i ) co_f[i] = r[i]; + for(size_t i = 0; i < N; ++i ) co_g[i] = r[i+(N+1)]; + range = 1./(max-min); + } + T operator()(const T& s) + { + T x = (s-min)*range; + T f = 0; + T g = 1; + T acc = 1; + for(size_t i = 0; i < N; ++i){ + f += co_f[i] * acc; + acc *= x; + g += co_g[i] * acc; } - }; + return (f + co_f[N]*acc)/g; + } + + private: + std::function m_function; + std::array co_f; + std::array co_g; + T min; + T max; + T range; + }; } #endif diff --git a/AmpGen/Particle.h b/AmpGen/Particle.h index fb2d33668f7..b3f9a9a9db1 100644 --- a/AmpGen/Particle.h +++ b/AmpGen/Particle.h @@ -126,56 +126,74 @@ namespace AmpGen /// Set the flag to say this void setTop( bool state = true ); + + /// Set the index of this particle, i.e. where it is positioned in the event data structure. void setIndex( const unsigned int& index, const bool& setOri = false ); + + /// Remove all of the decay products of this particle void clearDecayProducts(); + /// Add some modifier to the particle, such as a lineshape or a different spin state void addModifier( const std::string& mod ); + + /// Parse some set of modifiers, delimited with semicolons. void parseModifier( const std::string& mod ); + + /// Set some particle ordering of the decay products of this particle, mostly used internally by the symmetrisation void setOrdering( const std::vector& ordering ); + + /// Set the particle name void setName(const std::string& name); + + /// Add a decay product void addDaughter( const std::shared_ptr& particle ); + + /// Set the polarisation state of this particle, which is twice the projection of the spin along the quantisation axis. void setPolarisationState( const int& state ); /// Returns the range of orbital angular momentum between the decay products std::pair orbitalRange( const bool& converseParity = true ) const; + + /// Returns the set of possible spin-orbit couplings allowed by conservation of angular momentum, and if specified parity std::vector> spinOrbitCouplings( const bool& conserveParity = true ) const; + + /// Return the additional optional attribute keyed by variable key stdx::optional attribute(const std::string& key) const; + + /// Return the particleProperties object for this particle const ParticleProperties* props() const; - QuarkContent quarks() const; - QuarkContent daughterQuarks() const; - int parity() const; - int finalStateParity() const; - int polState() const; - double mass() const; - double spin() const; - double S() const; - bool isHead() const; - bool isWeakDecay() const; - bool isStateGood() const; - bool isStable() const; - bool isQuasiStable() const; - bool conservesParity( unsigned int L = 0 ) const; - - unsigned int orbital() const; - unsigned int index() const; - unsigned int originalIndex() const; - - /// Name of the decaying particle. - std::string name() const; - - /// Name of the propagator to use for the decay of this particle. - std::string lineshape() const; - - /// Name of the (spin)vertex to use for the decay of this particle - std::string vertexName() const; - - /// The unique string (i.e. decay descriptor) that identifies this decay / - /// can be parsed to generate the decay tree. - std::string uniqueString() const; - /// The descriptor that describes this decay / - /// that can be parsed to generate the decay tree and uniquely identify it. - std::string decayDescriptor() const; + QuarkContent quarks() const; ///< Return the quarks of this particle + + QuarkContent daughterQuarks() const; ///< Returns the quark content of the sum of the decay products of this particle + + int parity() const; ///< Returns the parity of this particle + int finalStateParity() const; ///< Returns the parity of the final state of this particle + + int polState() const; ///< Returns the polarisation state, i.e. twice the projection of the spin along the quantisation axis, of this particle. + int quasiCP() const; ///< Returns the ``quasi'' CP Quantum number for this decay, see the Particle + int C() const; ///< Returns the C quantum number for this decay + + double mass() const; ///< Returns the (PDG) mass of the particle + double spin() const; ///< Returns the spin of the particle + double S() const; + + bool isHead() const; ///< Returns whether if this particle is the head of the decay, i.e. has no parent + bool isWeakDecay() const; ///< Returns whether is this particle decays weakly or not + bool isStateGood() const; ///< Returns whether this particle, and its decays have been configured correctly + bool isStable() const; ///< Check whether this particle is stable, has any decay products. + bool isQuasiStable() const; ///< Check whether the particle is quasi-stable, i.e. may have some appreciable flight distance + bool conservesParity( unsigned int L = 0 ) const; ///< Check whether the decay of this particle with angular momentum L conserves parity or not + + unsigned int orbital() const; ///< Returns the orbital angular + unsigned int index() const; ///< Returns the current index of the particle in event data structure. Can differ from the original index due to symmetrisation + unsigned int originalIndex() const; ///< Returns the original index of the particle + std::string name() const; ///< Name of the decaying particle. + std::string lineshape() const; ///< Name of the propagator to use for the decay of this particle. + std::string vertexName() const; ///< Name of the (spin)vertex to use for the decay of this particle + + std::string uniqueString() const; ///< Returns the unique string (i.e. decay descriptor) that identifies this decay, which can be parsed to generate the decay tree. + std::string decayDescriptor() const;///< Returns the unique string (i.e. decay descriptor) that identifies this decay, which can be parsed to generate the decay tree. /// The string that describes the spin/orbital topology of this decay, /// i.e. replacing specific particle names with their spins. @@ -187,12 +205,6 @@ namespace AmpGen /// Decay descriptor formatted as LaTeX for this decay. std::string texLabel( const bool& printHead = false, const bool& recurse=true ) const; - /// Returns the ``quasi'' CP Quantum number for this decay, see the Particle - int quasiCP() const; - - /// Returns the C quantum number for this decay - int C() const; - /// Return the eventType for this decay (i.e. the initial and final state particles) EventType eventType() const; diff --git a/AmpGen/ParticleProperties.h b/AmpGen/ParticleProperties.h index 0e395000a47..97cc3c7a4d4 100644 --- a/AmpGen/ParticleProperties.h +++ b/AmpGen/ParticleProperties.h @@ -11,97 +11,99 @@ namespace AmpGen { - class ParticleProperties - { - private: - double m_mass; ///< mass [MeV] - double m_mErrPlus; ///< +ve mass error [MeV] - double m_mErrMinus; ///< -ve mass error [MeV] - double m_width; ///< width [MeV] - double m_wErrPlus; ///< +ve width error [MeV] - double m_wErrMinus; ///< -ve width error [MeV] - double m_radius; ///< hadronic radius - int m_Gparity; ///< G-parity - int m_parity; ///< Parity - int m_Cparity; ///< Charge 'parity' - int m_pdgID; ///< PDG id - int m_Rexist; ///< likelihood of existence, baryons only - int m_charge; ///< electrical charge - int m_twoSpin; ///< twice the spin - std::string m_isospin; ///< isospin - std::string m_JtotalSpin; ///< total spin - std::string m_name; ///< particle name - std::string m_quarks; ///< quark string - std::string m_texName; ///< latex label of particle - std::string m_chargeString; ///< string for particle charge - char m_Aformat; ///< anti-particle format character - char m_status; ///< status (estalished or not etc) - QuarkContent m_netQuarkContent; - bool m_isValid; - - void setRadius(); + /** @class ParticleProperties + @brief Class that contains the PDG properties (mass, width, charges, etc.) for a single particle species, + + Stores the information for a single particle species, the mass, the width, spin, various charges. + The data is typically loaded from ParticlePropertiesList, which loads from the PDG provided + \code{cpp} + mass_width.cvs + \endcode + See that more details. + */ - void antiQuarks(); - void antiQuarkContent(); - void antiCharge(); - int chargeFromString( const std::string& ch, bool& status ) const; - public: - double mass() const { return m_mass * MeV; } ///< returns mass of particle in MeV - double mErrPlus() const { return m_mErrPlus * MeV; } ///< returns +ve uncertainty on particle mass in MeV - double mErrMinus() const { return m_mErrMinus * MeV; } ///< returns -ve uncertainty on particle mass in MeV - double width() const { return m_width * MeV; } ///< returns width of particle in MeV - double wErrPlus() const { return m_wErrPlus * MeV; } ///< returns +ve uncertainty on particle width in MeV - double wErrMinus() const { return m_wErrMinus * MeV; } ///< returns -ve uncertainty on particle width in MeV - double radius() const; ///< returns the effective interaction radius of the particle, i.e. for the Blatt-Weisskopf factors - double lifetime() const; ///< returns the lifetime of the particle in ns + class ParticleProperties + { + public: + ParticleProperties( const std::string& pdg_string = "" ); ///< Constructor from a string formatted by the PDG convention. + double mass() const { return m_mass * MeV; } ///< Returns mass of particle in MeV + double mErrPlus() const { return m_mErrPlus * MeV; } ///< Returns +ve uncertainty on particle mass in MeV + double mErrMinus() const { return m_mErrMinus * MeV; } ///< Returns -ve uncertainty on particle mass in MeV + double width() const { return m_width * MeV; } ///< Returns width of particle in MeV + double wErrPlus() const { return m_wErrPlus * MeV; } ///< Returns +ve uncertainty on particle width in MeV + double wErrMinus() const { return m_wErrMinus * MeV; } ///< Returns -ve uncertainty on particle width in MeV + double radius() const; ///< Returns the effective interaction radius of the particle, i.e. for the Blatt-Weisskopf factors + double lifetime() const; ///< Returns the lifetime of the particle in ns - int G() const { return m_Gparity; } ///< returns the G-parity of the particle - int P() const { return m_parity; } ///< returns the parity of the particle - int C() const { return m_Cparity; } ///< returns the C-parity of the particle - int R() const { return m_Rexist; } - int pdgID() const { return m_pdgID; } - int twoSpin() const { return m_twoSpin; } - int charge() const { return m_charge; } - char S() const { return m_status; } - std::string I() const { return m_isospin; } - std::string J() const { return m_JtotalSpin; } - std::string label() const { return m_texName; } - std::string quarks() const { return m_quarks; } - std::string name() const; - std::string chargeString() const { return m_chargeString; } - std::string spinName() const; + int G() const { return m_Gparity; } ///< Returns the G-parity of the particle + int P() const { return m_parity; } ///< Returns the parity of the particle + int C() const { return m_Cparity; } ///< Returns the C-parity of the particle + int R() const { return m_Rexist; } ///< Returns the R-parity of the particle + int pdgID() const { return m_pdgID; } ///< Returns the PDG id of the particle. + int twoSpin() const { return m_twoSpin; } ///< Returns twice the spin of the particle + int charge() const { return m_charge; } ///< Returns the (electrical) charge of the particle + char S() const { return m_status; } ///< Returns the existence status of the particle, i.e. whether it is confirmed by multiple experiments + std::string I() const { return m_isospin; } ///< Returns the isospin of the particle as a string. + std::string J() const { return m_JtotalSpin; } ///< Returns the total angular momentum of the particle + std::string label() const { return m_texName; } ///< Returns the LaTeX formatted label for the particle + std::string name() const; ///< Returns the particle name + std::string spinName() const; ///< Returns the name of the particles spin. + bool isValid() const { return m_isValid; } ///< Check if the particle properties have been configured correctly + bool hasDistinctAnti() const; ///< Check if the particle has a distinct antiparticle + bool isNonResonant() const; ///< Check is this is a nonresonant `quasi-particle' + bool isFermion() const; ///< Check if the particle is a fermion, i.e. if the spin 1/2, 3/2, ... + bool isBoson() const; ///< Check if the particle is a boson, i.e. if the spin 0, 1, 2... + const QuarkContent& netQuarkContent() const { return m_netQuarkContent; } ///< Returns the particle's quark content - void setLabel( const std::string& label ) { m_texName = label; } - void setName( const std::string& name ) { m_name = name; } - const QuarkContent& netQuarkContent() const { return m_netQuarkContent; } - - bool isValid() const { return m_isValid; } + void setLabel( const std::string& label ) { m_texName = label; } ///< Set the LaTeX label of the particle + void setName( const std::string& name ) { m_name = name; } ///< Set the name of the particle - bool hasDistinctAnti() const; - bool barred() const; - bool isItsOwnAnti() const { return !hasDistinctAnti(); } + void print( std::ostream& out = std::cout ) const; - ParticleProperties( const std::string& pdg_string = "" ); + bool operator==( const ParticleProperties& rhs ) const; + bool operator< ( const ParticleProperties& rhs ) const; + bool operator> ( const ParticleProperties& rhs ) const; + bool operator<=( const ParticleProperties& rhs ) const; + bool operator>=( const ParticleProperties& rhs ) const; - void print( std::ostream& out = std::cout ) const; + bool antiThis(); ///< Change this particle to its antiparticle + ParticleProperties anti() const; ///< Return the antiparticle of this particle - bool operator==( const ParticleProperties& rhs ) const; - bool operator< ( const ParticleProperties& rhs ) const; - bool operator> ( const ParticleProperties& rhs ) const; - bool operator<=( const ParticleProperties& rhs ) const; - bool operator>=( const ParticleProperties& rhs ) const; + static const ParticleProperties* get( const std::string& name, const bool& quiet=false ); - bool antiThis(); - ParticleProperties anti() const; + private: + double m_mass; ///< mass [GeV] + double m_mErrPlus; ///< +ve mass error [GeV] + double m_mErrMinus; ///< -ve mass error [GeV] + double m_width; ///< width [GeV] + double m_wErrPlus; ///< +ve width error [GeV] + double m_wErrMinus; ///< -ve width error [GeV] + double m_radius; ///< hadronic radius + int m_Gparity; ///< G-parity + int m_parity; ///< Parity + int m_Cparity; ///< Charge 'parity' + int m_pdgID; ///< PDG id + int m_Rexist; ///< likelihood of existence, baryons only + int m_charge; ///< electrical charge + int m_twoSpin; ///< twice the spin + std::string m_isospin; ///< isospin + std::string m_JtotalSpin; ///< total spin + std::string m_name; ///< particle name + std::string m_quarks; ///< quark string + std::string m_texName; ///< latex label of particle + std::string m_chargeString; ///< string for particle charge + char m_Aformat; ///< anti-particle format character + char m_status; ///< status (estalished or not etc) + QuarkContent m_netQuarkContent; ///< The quark content of the state (uD, uud etc.) + bool m_isValid; ///< Flag to check whether the ParticleProperties have configured correctly - bool isNonResonant() const; - bool isFermion() const ; - bool isBoson() const; - static const ParticleProperties* get( const std::string& name, const bool& quiet=false ); + void antiQuarks(); + void antiCharge(); + int chargeFromString( const std::string& ch, bool& status ) const; }; -} // namespace AmpGen -std::ostream& operator<<( std::ostream& out, const AmpGen::ParticleProperties& pp ); + std::ostream& operator<<( std::ostream& out, const AmpGen::ParticleProperties& pp ); +} #endif // diff --git a/AmpGen/PhaseSpace.h b/AmpGen/PhaseSpace.h index ecd2b578ee2..a00b31f9cf1 100644 --- a/AmpGen/PhaseSpace.h +++ b/AmpGen/PhaseSpace.h @@ -10,40 +10,38 @@ namespace AmpGen { - /**@class PhaseSpace - * Phase-space generator taken from the ROOT routine, from Rene Brun and Valerio Filippini, - * which was originally based on the GENBOD routine of CERNLIB with - * modifications such that unweighted events are generated, - * which saves a large amount of CPU. Further modified to remove the dependencies on TLorentzVector - * and to only use the AmpGen::Event classes, and to add the option to include a time dependence. + /** @class PhaseSpace + Phase-space generator taken from the ROOT routine, from Rene Brun and Valerio Filippini, + which was originally based on the GENBOD routine of CERNLIB with + modifications such that unweighted events are generated, + which saves a large amount of CPU. Further modified to remove the dependencies on TLorentzVector + and to only use the AmpGen::Event classes, and to add the option to include a time dependence. */ class Particle; class PhaseSpace { public: - PhaseSpace() = default; - PhaseSpace( const EventType& type, TRandom* rand = gRandom ); - PhaseSpace( const Particle& type, TRandom* rand = gRandom ); - ~PhaseSpace() = default; + PhaseSpace() = default; ///< Empty constructor + PhaseSpace(const EventType& type, TRandom* rand = gRandom); ///< Construct a phase space generator from an EventType + PhaseSpace(const Particle& type, TRandom* rand = gRandom); ///< Construct a phase space generator from a Particle - bool setDecay( const double& m0, const std::vector& mass ); - void setRandom( TRandom* rand ) { m_rand = rand; } - size_t size() const { return m_nt; } - AmpGen::Event makeEvent( const size_t& cacheSize = 0 ); - AmpGen::EventType eventType() const; + bool setDecay( const double& m0, const std::vector& mass ); ///< Set the parameters of this phase space generator + void setRandom( TRandom* rand ) { m_rand = rand; } ///< Set the random number used by this phase space generator + size_t size() const { return m_nt; } ///< Return the number of decay products + Event makeEvent( const size_t& cacheSize = 0 ); ///< Make an event in this phase space. + EventType eventType() const; ///< Returns the EventType that this phase space is generating private: - size_t m_nt = {0}; // number of decay particles - double m_mass[18] = {0}; // masses of particles - double m_teCmTm = {0}; // total energy in the C.M. minus the total mass - double m_wtMax = {0}; // maximum weight - double m_decayTime = {0}; // decay time - TRandom* m_rand = {nullptr}; // Random number generator - EventType m_type; // EventType to generate + size_t m_nt = {0}; ///< Number of particles in the final state + double m_mass[18] = {0}; ///< Masses of particles in the final state + double m_teCmTm = {0}; ///< Total energy in the rest frame minus the total mass + double m_wtMax = {0}; ///< Maximum weight of an event + double m_decayTime = {0}; ///< Proper decay time of the particle + TRandom* m_rand = {nullptr}; ///< Random number generator + EventType m_type; ///< EventType to generate - double rndm() { return m_rand->Rndm(); } - double q(double a, double b, double c) const; + double q(double a, double b, double c) const; ///< Breakup momentum of a particle with mass a decaying to decay products with masses b and c. }; } // namespace AmpGen #endif diff --git a/AmpGen/Plots.h b/AmpGen/Plots.h index d5d62e43548..e21519cff8d 100644 --- a/AmpGen/Plots.h +++ b/AmpGen/Plots.h @@ -29,7 +29,7 @@ namespace AmpGen for ( unsigned int i = 0; i < fcn.size(); ++i ) { for ( unsigned int j = i; j < fcn.size(); ++j ) { - bid.addIntegral( fcn[i].pdf, fcn[j].pdf, [i, j, &normalisations]( const auto& val ) { + bid.addIntegral( fcn[i].amp, fcn[j].amp, [i, j, &normalisations]( const auto& val ) { for ( unsigned int bin = 0; bin < NBINS; ++bin ) { normalisations[bin].set( i, j, val[bin] ); if ( i != j ) normalisations[bin].set( j, i, std::conj( val[bin] ) ); @@ -47,7 +47,7 @@ namespace AmpGen std::array normalisations; for ( unsigned int i = 0; i < NBINS; ++i ) normalisations[i] = Bilinears( fcn.size(), fcn.size() ); for ( unsigned int i = 0; i < fcn.size(); ++i ) { - bid.addIntegral( fcn[i].pdf, fcn[i].pdf, [i, &normalisations]( const auto& val ) { + bid.addIntegral( fcn[i].amp, fcn[i].amp, [i, &normalisations]( const auto& val ) { for ( unsigned int bin = 0; bin < NBINS; ++bin ) normalisations[bin].set( i, 0, val[bin] ); } ); } diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index be04a85779e..7c8b240ee41 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -15,7 +15,7 @@ #include "AmpGen/CompiledExpression.h" #include "AmpGen/EventList.h" #include "AmpGen/EventType.h" -#include "AmpGen/Integrator.h" +#include "AmpGen/Integrator2.h" #include "AmpGen/CoherentSum.h" #include "AmpGen/Expression.h" #include "AmpGen/Tensor.h" @@ -51,8 +51,8 @@ namespace AmpGen Expression probExpression( const Tensor& T_matrix, const std::vector& p, DebugSymbols* = nullptr ) const; size_t size() const ; real_t norm() const; - complex_t norm(const size_t& i, const size_t& j, Integrator<18>* integ = nullptr ); - real_t operator()(const AmpGen::Event& event) const { return prob_unnormalised(event) ;} + complex_t norm(const size_t& i, const size_t& j, Integrator2<18>* integ = nullptr ); + inline real_t operator()(const AmpGen::Event& event) const { return m_weight * prob_unnormalised(event) / m_norm; } real_t prob_unnormalised( const AmpGen::Event& evt ) const; real_t prob(const AmpGen::Event& evt ) const ; real_t getValNoCache( const AmpGen::Event& evt ) ; @@ -72,7 +72,7 @@ namespace AmpGen std::vector m_pVector = {}; bool m_verbosity = {0}; bool m_debug = {0}; - Integrator<18> m_integrator; + Integrator2<18> m_integrator; std::vector m_norms; std::vector> m_polStates; EventType m_eventType; diff --git a/AmpGen/SimPDF.h b/AmpGen/SimPDF.h index ba46838a76b..ad47ef00d64 100644 --- a/AmpGen/SimPDF.h +++ b/AmpGen/SimPDF.h @@ -7,23 +7,25 @@ namespace AmpGen { class SimFit { - std::vector> m_pdfs; + public: + SimFit() = default; + double getVal() + { + double LL = 0; + for ( auto& pdf : m_pdfs ) LL += pdf(); + return LL; + } - public: - SimFit() {} - double getVal() - { - double LL = 0; - for ( auto& pdf : m_pdfs ) LL += pdf(); - return LL; - } + template + void add( PDF& pdf ) + { + INFO( "Adding " << &pdf << " to sim fit" ); + m_pdfs.emplace_back( [&pdf]() -> double { return pdf.getVal(); } ); + } + + private: + std::vector> m_pdfs; - template - void add( PDF& pdf ) - { - INFO( "Adding " << &pdf << " to sim fit" ); - m_pdfs.emplace_back( [&pdf]() -> double { return pdf.getVal(); } ); - } }; } // namespace AmpGen diff --git a/AmpGen/SumPDF.h b/AmpGen/SumPDF.h index c85196c033a..ed182afffba 100644 --- a/AmpGen/SumPDF.h +++ b/AmpGen/SumPDF.h @@ -1,7 +1,6 @@ #ifndef AMPGEN_SUMPDF_H #define AMPGEN_SUMPDF_H -#include "AmpGen/EventList.h" #include "AmpGen/IExtendLikelihood.h" #include "AmpGen/MetaUtils.h" #include "AmpGen/MsgService.h" @@ -11,25 +10,45 @@ namespace AmpGen { + class EventList; /** @class SumPDF - @brief A pdf with the log-likelihood of the form - -2*LL(event) = -2*log( Sum( i, P_i(event) ) ) - Where P_i are some probability density functions + @brief A pdf that contains one or more terms. + + A pdf with a probability of the form + @f[ + P(\psi) = \sum_{j} \mathcal{P}_j (\psi), + @f] + where @f$ \mathcal{P}_j(\psi) @f$ are some normalised probability density functions + as a function of position in the phase space @f$ \psi @f$ + , and the sum is over the different terms, typically a signal term and then a number of background terms. + The pdf is also equipped with a log-likelihood of the form: + @f[ + -2 \mathcal{L} = - 2 \sum_{i} \log \left( \sum_{j} \mathcal{P}_j \left(\psi_i\right) \right) + @f] + and the sum over @f$ i @f$ is over some dataset. + This combined functionality is largely historical and the two roles should be separated at some point in the future. The sum is variadically unrolled at compile time, i.e. the wrapper is the same for 1..N pdfs. The unrolling should be properly inlined, hence N can be reasonably large with out afflicting either - compile time or binary size. */ - template + compile time or binary size. It isn't primarily used as PDF, as its primary function is + as a likelihood via function getVal(). + Typically constructed using either the make_pdf helper function or make_likelihood helper function. */ + template class SumPDF { + private: + typedef typename eventListType::value_type eventValueType; ///< The value type stored in the eventListType + std::tuple m_pdfs; ///< The tuple of probability density functions + eventListType* m_events; ///< The event list to evaluate likelihoods on + public: + /// Default Constructor SumPDF() = default; - SumPDF( const TYPES&... _pdfs ) : m_pdfs( std::tuple( _pdfs... ) ) {} - std::tuple m_pdfs; - EventList* m_events; - std::tuple pdfs() const { return m_pdfs; } - + /// Constructor from a set of PDF functions + SumPDF( const pdfTypes&... pdfs ) : m_pdfs( std::tuple( pdfs... ) ) {} + + /// Returns negative twice the log-likelihood for this PDF and the given dataset. double getVal() { double LL = 0; @@ -41,30 +60,52 @@ namespace AmpGen } return -2 * LL; } - double operator()( const Event& evt ) + + /// Returns the probability for the given event. + double operator()( const eventValueType& evt ) { double prob = 0; - for_each( this->m_pdfs, [&prob, &evt]( auto& f ) { prob += f.prob( evt ); } ); + for_each( this->m_pdfs, [&prob, &evt]( auto& f ) { prob += f(evt); } ); return prob; } - void setEvents( EventList& events ) + + /// Sets the events to be summed over in the likelihood + void setEvents( eventListType& events ) { m_events = &events; for_each( m_pdfs, [&events]( auto& f ) { f.setEvents( events ); } ); } - template - void forEach( const FCN& fcn ) - { - for_each( m_pdfs, fcn ); - } - std::size_t nPDFs() { return sizeof...( TYPES ); } + /// Returns the number of PDFs contained by this function + std::size_t nPDFs() const { return sizeof...(pdfTypes); } + + /// Returns the tuple of PDFs used by this function + std::tuple pdfs() const { return m_pdfs; } }; - template - auto make_pdf( PDFS&&... pdfs ) + /** @function make_pdf + + Usage is + \code{cpp} + auto pdf = make_pdf( signal, bkg1, ... ); + \endcode + which returns a PDF that is the sum of the signal and bkg1 etc. The sum is also equipped with a likelihood, which can be used by setting + the data for the PDF. + Therefore, named SumPDF, it is useful to use this function to get a likelihood for a PDF containing a single term (i.e. signal or background only). + */ + template + auto make_pdf( pdfTypes&&... pdfs ) + { + //return SumPDF( std::forward( pdfs )... ); + return SumPDF( pdfs... ); + } + + template + auto make_likelihood( eventListType& events, pdfTypes&&... pdfs ) { - return SumPDF( std::forward( pdfs )... ); + auto rt = SumPDF( std::forward( pdfs )... ); + rt.setEvents(events); + return rt; } } // namespace AmpGen diff --git a/apps/ConvertToSourceCode.cpp b/apps/ConvertToSourceCode.cpp index 0896aeeb591..954e9290f84 100644 --- a/apps/ConvertToSourceCode.cpp +++ b/apps/ConvertToSourceCode.cpp @@ -48,8 +48,8 @@ void create_integration_tests(T& pdf, unit_tests << "\n}\n" << std::endl; for( auto& mE : pdf.matrixElements() ){ - auto value = mE.pdf(testEvents[0].address()); - unit_tests << "BOOST_AUTO_TEST_CASE( " << mE.pdf.progName() + "_test){" << std::endl; + auto value = mE.amp(testEvents[0].address()); + unit_tests << "BOOST_AUTO_TEST_CASE( " << mE.amp.progName() + "_test){" << std::endl; unit_tests << " EventType type({" << stringify(type.mother()) << ", " << vectorToString( type.finalStates(), ", ", stringify ) << "});" << std::endl; unit_tests << " Particle p("< void print( const Event& event, const MatrixElem for ( auto& term : terms ) { INFO( "--> " << term.first->name() << " = (" << term.first->mean() * cos( term.second->mean() ) << " + i " << term.first->mean() * sin( term.second->mean() ) << ")" ); } - mE.pdf.debug( event.address() ); + mE.amp.debug( event.address() ); } } } diff --git a/apps/Fitter.cpp b/apps/Fitter.cpp index 43315e7412f..d05d1430ba9 100644 --- a/apps/Fitter.cpp +++ b/apps/Fitter.cpp @@ -132,13 +132,9 @@ FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& // const size_t NBins = NamedParameter ("nBins" , 100 , "Number of bins used for plotting."); unsigned int counter = 1; - for_each( pdf.m_pdfs, [&]( auto& f ) { - std::function FCN_sig = - [&](const Event& evt){ return f.prob_unnormalised(evt) ; }; + for_each( pdf.pdfs(), [&]( auto& f ) { auto tStartIntegral2 = std::chrono::high_resolution_clock::now(); auto mc_plot3 = mc.makeProjections( mc.eventType().defaultProjections(100), WeightFunction(f), Prefix("tMC_Category"+std::to_string(counter) ) ); - - // auto mc_plot3 = bandPlot<100>( mc, "tMC_Category" + std::to_string( counter ) + "_", f, ep ); auto tEndIntegral2 = std::chrono::high_resolution_clock::now(); double t2 = std::chrono::duration( tEndIntegral2 - tStartIntegral2 ).count(); INFO( "Time for plots = " << t2 ); diff --git a/examples/FitterWithPolarisation.cpp b/examples/FitterWithPolarisation.cpp index 35f6dafb0af..fd2340c85f9 100644 --- a/examples/FitterWithPolarisation.cpp +++ b/examples/FitterWithPolarisation.cpp @@ -145,8 +145,7 @@ FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& /* Make the plots for the different components in the PDF, i.e. the signal and backgrounds. The structure assumed the PDF is some SumPDF. */ unsigned int counter = 1; - for_each(pdf.m_pdfs, [&]( auto& f ){ -// std::function FCN_sig = [&](const Event& evt){ return f.prob_unnormalised(evt) ; }; + for_each(pdf.pdfs(), [&]( auto& f ){ auto mc_plot3 = mc.makeDefaultProjections(WeightFunction(f), Prefix("Model_cat"+std::to_string(counter))); for( auto& plot : mc_plot3 ) { diff --git a/examples/SignalOnlyFitter.cpp b/examples/SignalOnlyFitter.cpp index 0b9ab9e25b2..0ca87852484 100644 --- a/examples/SignalOnlyFitter.cpp +++ b/examples/SignalOnlyFitter.cpp @@ -100,7 +100,7 @@ int main( int argc, char* argv[] ) /* Generate events to normalise the PDF with. This can also be loaded from a file, which will be the case when efficiency variations are included. Default number of normalisation events is 5 million. */ - EventList eventsMC = intFile == "" ? Generator<>(evtType, &rndm).generate(5e6) : EventList(intFile, evtType, GetGenPdf(true)); + EventList eventsMC = intFile == "" ? Generator<>(evtType, &rndm).generate(2e6) : EventList(intFile, evtType, GetGenPdf(true)); sig.setMC( eventsMC ); @@ -108,7 +108,7 @@ int main( int argc, char* argv[] ) /* Do the fit and return the fit results, which can be written to the log and contains the covariance matrix, fit parameters, and other observables such as fit fractions */ - FitResult* fr = doFit(make_pdf(sig), events, eventsMC, MPS ); + FitResult* fr = doFit(make_likelihood(events, sig), events, eventsMC, MPS ); /* Calculate the `fit fractions` using the signal model and the error propagator (i.e. fit results + covariance matrix) of the fit result, and write them to a file. */ @@ -127,46 +127,44 @@ int main( int argc, char* argv[] ) output->Close(); } -template -FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& MPS ) +template +FitResult* doFit( likelihoodType&& likelihood, EventList& data, EventList& mc, MinuitParameterSet& MPS ) { auto time_wall = std::chrono::high_resolution_clock::now(); auto time = std::clock(); - - pdf.setEvents( data ); - /* Minimiser is a general interface to Minuit1/Minuit2, that is constructed from an object that defines an operator() that returns a double (i.e. the likielihood, and a set of MinuitParameters. */ - Minimiser mini( pdf, &MPS ); + Minimiser mini( likelihood, &MPS ); mini.doFit(); FitResult* fr = new FitResult(mini); + + auto twall_end = std::chrono::high_resolution_clock::now(); + double time_cpu = ( std::clock() - time ) / (double)CLOCKS_PER_SEC; + double tWall = std::chrono::duration( twall_end - time_wall ).count(); + INFO( "Wall time = " << tWall / 1000. ); + INFO( "CPU time = " << time_cpu ); /* Make the plots for the different components in the PDF, i.e. the signal and backgrounds. - The structure assumed the PDF is some SumPDF. */ + The structure assumed the PDF is some SumPDF. */ unsigned int counter = 1; - for_each(pdf.m_pdfs, [&]( auto& f ){ - std::function FCN_sig = [&](const Event& evt){ return f.prob_unnormalised(evt) ; }; - auto mc_plot3 = mc.makeDefaultProjections(WeightFunction(f), Prefix("Model_cat"+std::to_string(counter))); + for_each(likelihood.pdfs(), [&](auto& pdf){ + auto pfx = Prefix("Model_cat"+std::to_string(counter)); + auto mc_plot3 = mc.makeDefaultProjections(WeightFunction(pdf), pfx); for( auto& plot : mc_plot3 ) { - plot->Scale( ( data.integral() * f.getWeight() ) / plot->Integral() ); + plot->Scale( ( data.integral() * pdf.getWeight() ) / plot->Integral() ); plot->Write(); } counter++; - } ); + }); /* Estimate the chi2 using an adaptive / decision tree based binning, down to a minimum bin population of 15, and add it to the output. */ - Chi2Estimator chi2( data, mc, pdf, 15 ); + Chi2Estimator chi2( data, mc, likelihood, 15 ); chi2.writeBinningToFile("chi2_binning.txt"); fr->addChi2( chi2.chi2(), chi2.nBins() ); - auto twall_end = std::chrono::high_resolution_clock::now(); - double time_cpu = ( std::clock() - time ) / (double)CLOCKS_PER_SEC; - double tWall = std::chrono::duration( twall_end - time_wall ).count(); - INFO( "Wall time = " << tWall / 1000. ); - INFO( "CPU time = " << time_cpu ); fr->print(); return fr; } diff --git a/examples/SimFit.cpp b/examples/SimFit.cpp index 824b769626c..14aacf18ff7 100644 --- a/examples/SimFit.cpp +++ b/examples/SimFit.cpp @@ -60,7 +60,7 @@ int main(int argc , char* argv[] ){ } std::vector fcs(data.size()); - std::vector> pdfs; + std::vector> pdfs; pdfs.reserve(data.size()); @@ -69,10 +69,10 @@ int main(int argc , char* argv[] ){ mps.loadFromStream(); for(size_t i = 0; i < data.size(); ++i){ fcs[i] = PolarisedSum(eventType, mps); - pdfs.emplace_back( make_pdf(fcs[i] ) ); + pdfs.emplace_back( make_pdf(fcs[i]) ); pdfs[i].setEvents(data[i]); auto& mc = mcs[i]; - pdfs[i].forEach([&mc](auto& pdf){pdf.setMC(mc);}); + for_each( pdfs[i].pdfs(), [&mc](auto& pdf){pdf.setMC(mc);}); totalLL.add( pdfs[i] ); } Minimiser mini( totalLL, &mps ); @@ -85,8 +85,9 @@ int main(int argc , char* argv[] ){ auto dataPlots = data[i].makeDefaultProjections( Prefix("Data_"+std::to_string(i))); for( auto& p : dataPlots ) p->Write(); size_t counter = 0; - for_each(pdfs[i].m_pdfs, [&]( auto& f ){ - auto mc_plots = mcs[i].makeDefaultProjections(WeightFunction(f), Prefix("Model_sample_"+std::to_string(i)+"_cat"+std::to_string(counter))); + for_each(pdfs[i].pdfs(), [&]( auto& f ){ + auto mc_plots = mcs[i].makeDefaultProjections(WeightFunction(f), + Prefix("Model_sample_"+std::to_string(i)+"_cat"+std::to_string(counter))); for( auto& plot : mc_plots ) { plot->Scale( ( data[i].integral() * f.getWeight() ) / plot->Integral() ); diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 8cef77954a1..e289a5717a3 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -51,7 +51,7 @@ CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, for(size_t i = 0; i < m_matrixElements.size(); ++i){ tp.enqueue( [i,this,&mps,&litudes]{ m_matrixElements[i] = TransitionMatrix( amplitudes[i].first, amplitudes[i].second, mps, this->m_evtType.getEventFormat(), this->m_dbThis); - CompilerWrapper().compile( m_matrixElements[i].pdf, this->m_objCache); } ); + CompilerWrapper().compile( m_matrixElements[i].amp, this->m_objCache); } ); } m_isConstant = false ; } @@ -64,24 +64,24 @@ void CoherentSum::prepare() std::vector changedPdfIndices; ProfileClock clockEval; bool printed = false; - for ( unsigned int i = 0; i < m_matrixElements.size(); ++i ) { - auto& pdf = m_matrixElements[i].pdf; - pdf.prepare(); - if ( m_prepareCalls != 0 && !pdf.hasExternalsChanged() ) continue; + for ( size_t i = 0; i < m_matrixElements.size(); ++i ) { + auto& amp = m_matrixElements[i].amp; + amp.prepare(); + if ( m_prepareCalls != 0 && !amp.hasExternalsChanged() ) continue; ProfileClock clockThisElement; if ( m_events != nullptr ) { if ( m_matrixElements[i].addressData == 999 ) - m_matrixElements[i].addressData = m_events->registerExpression( pdf ); - m_events->updateCache( pdf, m_matrixElements[i].addressData ); + m_matrixElements[i].addressData = m_events->registerExpression( amp ); + m_events->updateCache( amp, m_matrixElements[i].addressData ); } else if ( i == 0 && m_verbosity ) WARNING( "No data events specified for " << this ); clockThisElement.stop(); if ( m_verbosity && ( m_prepareCalls > m_lastPrint + m_printFreq || m_prepareCalls == 0 ) ) { - INFO( pdf.name() << " (t = " << clockThisElement << " ms, nCalls = " << m_prepareCalls << ", events = " << m_events->size() << ")" ); + INFO( amp.name() << " (t = " << clockThisElement << " ms, nCalls = " << m_prepareCalls << ", events = " << m_events->size() << ")" ); printed = true; } changedPdfIndices.push_back(i); - pdf.resetExternals(); + amp.resetExternals(); } clockEval.stop(); ProfileClock clockIntegral; @@ -101,10 +101,10 @@ void CoherentSum::prepare() void CoherentSum::updateNorms( const std::vector& changedPdfIndices ) { - for ( auto& i : changedPdfIndices ) m_integrator.prepareExpression( m_matrixElements[i].pdf ); + for ( auto& i : changedPdfIndices ) m_integrator.prepareExpression( m_matrixElements[i].amp ); std::vector cacheIndex; std::transform( m_matrixElements.begin(), m_matrixElements.end(), std::back_inserter(cacheIndex), - [this](auto& m){ return this->m_integrator.events().getCacheIndex( m.pdf ) ; } ); + [this](auto& m){ return this->m_integrator.getCacheIndex( m.amp ) ; } ); for ( auto& i : changedPdfIndices ) for ( size_t j = 0; j < size(); ++j ) m_integrator.queueIntegral( cacheIndex[i], cacheIndex[j] ,i, j, &m_normalisations ); @@ -115,19 +115,19 @@ void CoherentSum::updateNorms( const std::vector& changedPdfIndice void CoherentSum::debug( const Event& evt, const std::string& nameMustContain ) { prepare(); - for ( auto& pdf : m_matrixElements ) pdf.pdf.resetExternals(); + for ( auto& me : m_matrixElements ) me.amp.resetExternals(); if ( nameMustContain == "" ) - for ( auto& pdf : m_matrixElements ) { - auto A = pdf(evt); - INFO( std::setw(70) << pdf.decayTree.uniqueString() - << " A = [ " << std::real(A) << " " << std::imag(A) - << " ] g = [ "<< std::real(pdf.coupling()) << " " << std::imag(pdf.coupling()) << " ]" ); - if( m_dbThis ) pdf.pdf.debug( evt.address() ); - pdf.coupling.print(); + for ( auto& me : m_matrixElements ) { + auto A = me(evt); + INFO( std::setw(70) << me.decayTree.uniqueString() + << " A = [ " << std::real(A) << " " << std::imag(A) + << " ] g = [ "<< std::real(me.coupling()) << " " << std::imag(me.coupling()) << " ]" ); + if( m_dbThis ) me.amp.debug( evt.address() ); + me.coupling.print(); } else - for ( auto& pdf : m_matrixElements ) - if ( pdf.pdf.name().find( nameMustContain ) != std::string::npos ) pdf.pdf.debug( evt.address() ); + for ( auto& me : m_matrixElements ) + if ( me.amp.name().find( nameMustContain ) != std::string::npos ) me.amp.debug( evt.address() ); if( evt.cacheSize() != 0 ) INFO( "Pdf = " << prob_unnormalised( evt ) ); INFO( "A(x) = " << getVal(evt) ); } @@ -179,16 +179,16 @@ void CoherentSum::generateSourceCode(const std::string& fname, const double& nor bool includePythonBindings = NamedParameter("CoherentSum::IncludePythonBindings",false); for ( auto& p : m_matrixElements ){ - stream << p.pdf << std::endl; - p.pdf.compileWithParameters( stream ); - if( includePythonBindings ) p.pdf.compileDetails( stream ); + stream << p.amp << std::endl; + p.amp.compileWithParameters( stream ); + if( includePythonBindings ) p.amp.compileDetails( stream ); } Expression event = Parameter("x0",0,true); Expression pa = Parameter("double(x1)",0,true); Expression amplitude; for( unsigned int i = 0 ; i < size(); ++i ){ auto& p = m_matrixElements[i]; - Expression this_amplitude = p.coupling() * Function( programatic_name( p.pdf.name() ) + "_wParams", {event} ); + Expression this_amplitude = p.coupling() * Function( programatic_name( p.amp.name() ) + "_wParams", {event} ); amplitude = amplitude + ( p.decayTree.finalStateParity() == 1 ? 1 : pa ) * this_amplitude; } stream << CompiledExpression< std::complex, const double*, const int&>( amplitude , "AMP" ) << std::endl; @@ -199,7 +199,7 @@ void CoherentSum::generateSourceCode(const std::string& fname, const double& nor stream << "extern \"C\" const char* matrix_elements(int n) {\n"; for ( size_t i = 0; i < m_matrixElements.size(); i++ ) { - stream << " if(n ==" << i << ") return \"" << m_matrixElements.at(i).pdf.progName() << "\" ;\n"; + stream << " if(n ==" << i << ") return \"" << m_matrixElements.at(i).amp.progName() << "\" ;\n"; } stream << " return 0;\n}\n"; stream << "extern \"C\" void FCN_all(double* out, double* events, unsigned int size, int parity, double* amps){\n"; @@ -221,7 +221,7 @@ void CoherentSum::generateSourceCode(const std::string& fname, const double& nor int parity = p.decayTree.finalStateParity(); if ( parity == -1 ) stream << "double(parity) * "; stream << "std::complex(amps[" << i * 2 << "],amps[" << i * 2 + 1 << "]) * "; - stream << programatic_name( p.pdf.name() )<< "_wParams( E )"; + stream << programatic_name( p.amp.name() )<< "_wParams( E )"; stream << ( i == size() - 1 ? ";" : " +" ) << "\n"; } stream << " out[i] = std::norm(amplitude) / " << normalisation << ";\n }\n}\n"; @@ -278,7 +278,7 @@ void CoherentSum::reset( bool resetEvents ) for ( auto& mE : m_matrixElements ) mE.addressData = 999; if ( resetEvents ){ m_events = nullptr; - m_integrator = Integrator<10>(); + m_integrator = integrator(); } } @@ -293,7 +293,7 @@ void CoherentSum::setMC( EventList& sim ) { if ( m_verbosity ) INFO( "Setting MC = " << &sim << " for " << this ); reset(); - m_integrator = Integrator<10>(&sim); + m_integrator = integrator(&sim); } real_t CoherentSum::norm() const @@ -343,7 +343,7 @@ std::vector CoherentSum::cacheAddresses( const EventList& evts ) c { std::vector addresses; std::transform( m_matrixElements.begin(), m_matrixElements.end(), std::back_inserter(addresses), - [&evts](auto& it ){ return evts.getCacheIndex( it.pdf ) ; } ); + [&evts](auto& it ){ return evts.getCacheIndex( it.amp ) ; } ); return addresses; } diff --git a/src/EventType.cpp b/src/EventType.cpp index 7c747287767..b63e839dcd0 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -109,15 +109,6 @@ std::pair EventType::count(const size_t& index) const return rt; } -std::vector> EventType::getBosePairs() const -{ - std::map> particleOrdering; - for ( unsigned int i = 0; i < m_particleNames.size(); ++i ) particleOrdering[m_particleNames[i]].push_back( i ); - std::vector> orderings; - for ( auto& im : particleOrdering ) - if ( im.second.size() != 1 ) orderings.push_back( im.second ); - return orderings; -} std::vector EventType::finalStates() const { return m_particleNames; } std::vector EventType::masses() const { return m_particleMasses; } @@ -202,7 +193,13 @@ size_t EventType::dof() const { return 3 * size() - 7; } std::function EventType::symmetriser() const { - auto shuffles = getBosePairs(); + std::map> particleOrdering; + for ( size_t i = 0; i < m_particleNames.size(); ++i ) + particleOrdering[m_particleNames[i]].push_back( i ); + std::vector> shuffles; + for ( auto& im : particleOrdering ) + if ( im.second.size() != 1 ) shuffles.push_back( im.second ); + int seed = NamedParameter( "EventType::SymmetriserSeed", 12 ); std::mt19937 rng( seed ); for ( auto& shuffle : shuffles ) { diff --git a/src/IncoherentSum.cpp b/src/IncoherentSum.cpp index 68ca1ede38f..4760c16f6ba 100644 --- a/src/IncoherentSum.cpp +++ b/src/IncoherentSum.cpp @@ -43,23 +43,21 @@ void IncoherentSum::prepare() if ( m_isConstant && m_prepareCalls != 0 ) return; transferParameters(); for ( auto& mE : m_matrixElements ) { - auto& pdf = mE.pdf; - pdf.prepare(); - if ( m_prepareCalls != 0 && !pdf.hasExternalsChanged() ) continue; + auto& amp = mE.amp; + amp.prepare(); + if ( m_prepareCalls != 0 && !amp.hasExternalsChanged() ) continue; if ( m_prepareCalls == 0 && m_events != nullptr ) - mE.addressData = m_events->registerExpression( pdf ); - - if ( m_events != nullptr ) m_events->updateCache( pdf, mE.addressData ); + mE.addressData = m_events->registerExpression( amp ); + if ( m_events != nullptr ) m_events->updateCache( amp, mE.addressData ); if ( m_prepareCalls == 0 && m_integrator.isReady() ){ - m_integrator.prepareExpression( pdf ); + m_integrator.prepareExpression( amp ); } INFO( mE.addressData << " " << m_events->at(0).getCache(mE.addressData) ); - pdf.resetExternals(); + amp.resetExternals(); } if( m_prepareCalls == 0 ){ for( size_t i = 0 ; i < m_matrixElements.size(); ++i ){ - auto& mE = m_matrixElements[i]; - auto index = m_integrator.events().getCacheIndex( mE.pdf ); + auto index = m_integrator.events().getCacheIndex( m_matrixElements[i].amp ); m_integrator.queueIntegral( index, index, i, 0, &m_normalisations, false); } m_integrator.flush(); diff --git a/src/Lineshapes/GounarisSakurai.cpp b/src/Lineshapes/GounarisSakurai.cpp index 43a664952b9..4db2c02832f 100644 --- a/src/Lineshapes/GounarisSakurai.cpp +++ b/src/Lineshapes/GounarisSakurai.cpp @@ -43,12 +43,14 @@ DEFINE_LINESHAPE( GounarisSakurai ) Expression t3 = (s0-s)/q(s0); Expression M2 = s0 + width0 * (t1 + t2 + t3 )/M_PI; - - Expression D = M2 - 1i*mass*width(s,s1,s2,mass,width0,0,L); + bool useRadius = lineshapeModifier.find("IncludeRadiusInWidth") != std::string::npos; + bool normalisedFF = lineshapeModifier.find("BL") != std::string::npos; + Expression D = M2 - 1i*mass*width(s, s1, s2, mass, width0, useRadius ? radius : 0, L); const Expression q2 = abs( Q2( s, s1, s2 ) ); Expression FormFactor = sqrt( BlattWeisskopf_Norm( q2 * radius * radius, 0, L ) ); - if ( lineshapeModifier == "BL" ) FormFactor = sqrt( BlattWeisskopf( q2 * radius * radius, L ) ); + if ( normalisedFF ) FormFactor = sqrt( BlattWeisskopf( q2 * radius * radius, L ) ); ADD_DEBUG( FormFactor , dbexpressions); ADD_DEBUG( M2 , dbexpressions); + ADD_DEBUG( D, dbexpressions); return kFactor( mass, width0, dbexpressions ) * FormFactor / (D-s); } diff --git a/src/Pade.cpp b/src/Pade.cpp new file mode 100644 index 00000000000..aa57158a7fa --- /dev/null +++ b/src/Pade.cpp @@ -0,0 +1,30 @@ +#include "AmpGen/Pade.h" +#include "TMatrixD.h" +#include "TVectorD.h" + + +std::vector AmpGen::detail::solve_pade(const std::function& fcn, + const double& min, + const double& max, + const int& N, + const AmpGen::Strategy& strat = AmpGen::Strategy::linear) +{ + + TMatrixD solver(2*N+1,2*N+1); + std::vector samples(2*N+1); + if( strat < 4 ){ + for(size_t eq = 0 ; eq < 2*N+1; ++eq) + samples[eq] = pow( eq/double(2*N), strat + 1); + } + TVectorD rest(2*N+1); + for( int eq = 0 ; eq < 2*N+1; ++eq ){ + rest(eq) = fcn( samples[eq]*(max-min) + min); + for(int i = 0; i <= N; ++i) solver(eq,i) = pow(samples[eq],i); + for(int i = 1; i <= N; ++i) solver(eq,i+N) = -rest(eq)* pow(samples[eq],i); + } + solver.Invert(); + auto r = solver * rest; + std::vector rv(2*N+1); + for( size_t i =0;i<2*N+1;++i) rv[i] = r[i]; + return rv; +} diff --git a/src/Particle.cpp b/src/Particle.cpp index 5073aa59e09..e1471d58dca 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -730,11 +730,11 @@ void Particle::setDaughter( const Particle& particle, const unsigned int& index std::vector> Particle::daughters() const { return m_daughters; } bool Particle::operator<( const Particle& other ) { - if ( spin() != other.spin() ) return spin() > other.spin(); - if ( !isStable() && other.isStable() ) return true; - if ( isStable() && !other.isStable() ) return false; - if ( mass() != other.mass() ) return mass() > other.mass(); - if ( std::abs( props()->pdgID() ) == std::abs( other.props()->pdgID() ) + if ( spin() != other.spin() ) return spin() > other.spin(); + if ( !isStable() && other.isStable() ) return true; + if ( isStable() && !other.isStable() ) return false; + if ( mass() != other.mass() ) return mass() > other.mass(); + if ( std::abs(props()->pdgID()) == std::abs(other.props()->pdgID() ) && props()->pdgID() != other.props()->pdgID() ) return props()->pdgID() > other.props()->pdgID(); if ( props()->charge() != other.props()->charge() ) return props()->charge() > other.props()->charge(); if ( props()->pdgID() != other.props()->pdgID() ) return props()->pdgID() > other.props()->pdgID(); diff --git a/src/ParticleProperties.cpp b/src/ParticleProperties.cpp index 4c460e3dad5..c5ad46bc041 100644 --- a/src/ParticleProperties.cpp +++ b/src/ParticleProperties.cpp @@ -18,9 +18,9 @@ void ParticleProperties::print( std::ostream& out ) const { out << "Mass " << mass() << " +" << mErrPlus() << " -" << mErrMinus() << "\nWidth " << width() << " +" << wErrPlus() << " -" << wErrMinus() << "\n I=" << I() << ", G=" << G() << "\n J=" << J() << ", C=" << C() << ", P=" << P() - << "\n Q = " << charge() << "\n pdgID " << pdgID() << "\n name " << name() << "\n quark content: " << quarks() + << "\n Q = " << charge() << "\n pdgID " << pdgID() << "\n name " << name() << "\n net-quark-content " << netQuarkContent() << "\n is its own antiparticle? " - << ( isItsOwnAnti() ? "yes" : "no" ) << "\n radius " << radius() * GeV << " /GeV" + << ( hasDistinctAnti() ? "no" : "yes" ) << "\n radius " << radius() * GeV << " /GeV" << "\n"; } @@ -29,8 +29,8 @@ int ParticleProperties::chargeFromString( const std::string& ch, bool& status ) if ( ch == "+" ) return 1; if ( ch == "-" ) return -1; if ( ch == " " ) return 0; - if ( ch == "0" ) return 0; - if ( ch == "++" ) return 2; + if ( ch == "0" ) return 0; + if ( ch == "++" ) return 2; if ( ch == "--" ) return -2; status = 0; return 0; @@ -77,56 +77,36 @@ ParticleProperties::ParticleProperties( const std::string& pdg_string ) : m_netQ if( spin_status == 0 ){ DEBUG("Spin of particle: " << name() << " could not be interpretted (J=" << m_JtotalSpin << ")" ); } - setRadius(); - m_isValid = true; -} - -void ParticleProperties::setRadius() -{ - double defaultRadius = 1.5 / GeV; // 1.5/GeV; - double defaultCharmRadius = 5.0 / GeV; + m_radius = 1.5 / GeV; bool isCharm = ( abs(pdgID()) == 421 || abs(pdgID()) == 411 || abs(pdgID()) == 431 || abs(pdgID()) == 4122 ); - m_radius = isCharm ? defaultCharmRadius : defaultRadius; -} - - - -void ParticleProperties::antiQuarks() -{ - if ( m_quarks.empty() ) return; - swapChars(m_quarks, 'U', 'u'); - swapChars(m_quarks, 'D', 'd'); - swapChars(m_quarks, 'C', 'c'); - swapChars(m_quarks, 'S', 's'); - swapChars(m_quarks, 'T', 't'); - swapChars(m_quarks, 'B', 'b'); - unsigned int pos = m_quarks.find( "SqrT" ); - if ( pos < m_quarks.size() ) { - m_quarks.replace( pos, 4, "sqrt" ); - } + if(isCharm) m_radius = 5.0 / GeV; + m_isValid = true; } -void ParticleProperties::antiQuarkContent() { m_netQuarkContent.antiThis(); } - -void ParticleProperties::antiCharge() -{ - swapChars( m_chargeString, '+', '-'); - m_charge *= -1; - if( isFermion() ) m_parity *= -1; -} bool ParticleProperties::hasDistinctAnti() const { return !( m_Aformat == ' ' ); } -bool ParticleProperties::barred() const { return m_Aformat == 'F'; } - bool ParticleProperties::antiThis() { if ( !hasDistinctAnti() ) return false; - antiCharge(); - antiQuarks(); - antiQuarkContent(); + swapChars( m_chargeString, '+', '-'); + m_charge *= -1; + if( isFermion() ) m_parity *= -1; + if ( !m_quarks.empty() ){ + swapChars(m_quarks, 'U', 'u'); + swapChars(m_quarks, 'D', 'd'); + swapChars(m_quarks, 'C', 'c'); + swapChars(m_quarks, 'S', 's'); + swapChars(m_quarks, 'T', 't'); + swapChars(m_quarks, 'B', 'b'); + unsigned int pos = m_quarks.find( "SqrT" ); + if ( pos < m_quarks.size() ) { + m_quarks.replace( pos, 4, "sqrt" ); + } + } + m_netQuarkContent.antiThis(); m_pdgID *= -1; return true; } @@ -166,7 +146,7 @@ bool ParticleProperties::isBoson() const { return ! isFermion(); } -std::ostream& operator<<( std::ostream& out, const ParticleProperties& pp ) +std::ostream& AmpGen::operator<<( std::ostream& out, const ParticleProperties& pp ) { pp.print( out ); return out; diff --git a/src/PhaseSpace.cpp b/src/PhaseSpace.cpp index d87d8307671..7eedb1b3f2c 100644 --- a/src/PhaseSpace.cpp +++ b/src/PhaseSpace.cpp @@ -49,7 +49,7 @@ Event PhaseSpace::makeEvent(const size_t& cacheSize) do { wt = m_wtMax; rno[0] = 0; - for( n = 1; n < m_nt - 1; n++ ) rno[n] = rndm(); // m_nt-2 random numbers + for( n = 1; n < m_nt - 1; n++ ) rno[n] = m_rand->Rndm(); // m_nt-2 random numbers rno[m_nt - 1] = 1; std::sort( rno.begin() + 1, rno.begin() + m_nt ); double sum = 0; @@ -61,15 +61,15 @@ Event PhaseSpace::makeEvent(const size_t& cacheSize) pd[n] = q( invMas[n + 1], invMas[n], m_mass[n + 1] ); wt *= pd[n]; } - } while ( wt < rndm() ); + } while ( wt < m_rand->Rndm() ); rt.set(0, { 0, pd[0], 0, sqrt( pd[0] * pd[0] + m_mass[0] * m_mass[0] )} ); for(size_t i = 1 ; i != m_nt ; ++i ){ rt.set( i, { 0, -pd[i-1], 0, sqrt( pd[i-1] * pd[i-1] + m_mass[i] * m_mass[i] ) } ); - double cZ = 2 * rndm() - 1; + double cZ = 2 * m_rand->Rndm() - 1; double sZ = sqrt( 1 - cZ * cZ ); - double angY = 2 * M_PI * rndm(); + double angY = 2 * M_PI * m_rand->Rndm(); double cY = cos(angY); double sY = sin(angY); for (size_t j = 0; j <= i; j++ ) { diff --git a/src/Plots.cpp b/src/Plots.cpp index 3a41d57b369..ac96b8bcc18 100644 --- a/src/Plots.cpp +++ b/src/Plots.cpp @@ -43,10 +43,10 @@ void AmpGen::perAmplitudePlot( const EventList& evts, for ( unsigned int i = 0; i < pdf.size(); ++i ) { for ( unsigned int j = i; j < pdf.size(); ++j ) { - auto pdf_i = pdf[i].pdf; - auto pdf_j = pdf[j].pdf; - unsigned int index_i = evts.getCacheIndex( pdf[i].pdf ); - unsigned int index_j = evts.getCacheIndex( pdf[j].pdf ); + auto pdf_i = pdf[i].amp; + auto pdf_j = pdf[j].amp; + unsigned int index_i = evts.getCacheIndex(pdf_i); + unsigned int index_j = evts.getCacheIndex(pdf_j); const std::string name = pdf_i.name() + "_" + pdf_j.name(); tmpPlots[s].hist = projection.plot(name); tmpPlots[s].i = index_i; diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 6e8f260e020..44962f24a99 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -70,7 +70,7 @@ PolarisedSum::PolarisedSum( const EventType& type, } if(autoCompile){ ThreadPool tp(8); - for( auto& thing : m_matrixElements ) tp.enqueue([&]{ CompilerWrapper().compile(thing.pdf, objCache);}); + for( auto& me : m_matrixElements ) tp.enqueue([&]{ CompilerWrapper().compile(me.amp, objCache);}); } auto d = m_eventType.dim(); auto p = [&mps](const std::string& name){ return mps.addOrGet(name,2,0,0); }; @@ -157,15 +157,15 @@ void PolarisedSum::prepare() for( size_t i = 0; i < m_matrixElements.size(); ++i ){ ProfileClock tMEval; auto& t = m_matrixElements[i]; - if( m_nCalls != 0 && !t.pdf.hasExternalsChanged() ) continue; - if( t.addressData == 999 ) t.addressData = m_events->registerExpression( t.pdf , dim.first * dim.second ); - m_events->updateCache(t.pdf, t.addressData); - m_integrator.prepareExpression(t.pdf, size_of); + if( m_nCalls != 0 && !t.amp.hasExternalsChanged() ) continue; + if( t.addressData == 999 ) t.addressData = m_events->registerExpression(t.amp, dim.first * dim.second ); + m_events->updateCache(t.amp, t.addressData); + m_integrator.prepareExpression(t.amp, size_of); tMEval.stop(); - t.pdf.resetExternals(); + t.amp.resetExternals(); hasChanged[i] = true; nChanges++; - if( m_nCalls == 0 && m_integrator.isReady() ) m_integIndex.push_back( m_integrator.events().getCacheIndex( t.pdf ) ); + if( m_nCalls == 0 && m_integrator.isReady() ) m_integIndex.push_back( m_integrator.events().getCacheIndex( t.amp ) ); } if( !m_probExpression.isLinked() ) build_probunnormalised(); m_weight = m_weightParam == nullptr ? 1 : m_weightParam->mean(); @@ -213,7 +213,7 @@ void PolarisedSum::setEvents( EventList& events ) void PolarisedSum::setMC( EventList& events ) { m_nCalls = 0; - m_integrator = Integrator<18>(&events); + m_integrator = Integrator2<18>(&events); } size_t PolarisedSum::size() const @@ -240,7 +240,7 @@ Tensor PolarisedSum::transitionMatrix() std::vector expressions(size, 0); for( auto& me : m_matrixElements ){ auto coupling = me.coupling.to_expression() ; - auto cacheIndex = m_events->getCacheIndex(me.pdf); + auto cacheIndex = m_events->getCacheIndex(me.amp); for( size_t i = 0 ; i < size ; ++i ){ expressions[i] = expressions[i] + coupling * Parameter( "x1["+std::to_string(cacheIndex+i)+"]",0,true); } @@ -260,7 +260,7 @@ double PolarisedSum::norm() const return m_norm; } -complex_t PolarisedSum::norm(const size_t& i, const size_t& j, Integrator<18>* integ) +complex_t PolarisedSum::norm(const size_t& i, const size_t& j, Integrator2<18>* integ) { auto ai = m_integIndex[i]; auto aj = m_integIndex[j]; @@ -328,10 +328,10 @@ void PolarisedSum::generateSourceCode(const std::string& fname, const double& no Expression event = Parameter("x0",0,true); std::vector expressions(size); for( auto& p : m_matrixElements ){ - p.pdf.prepare(); - p.pdf.to_stream( stream ); - p.pdf.compileWithParameters( stream ); - Array z( make_cse( Function( programatic_name( p.pdf.name()) + "_wParams", {event} ) ), size ); + p.amp.prepare(); + p.amp.to_stream( stream ); + p.amp.compileWithParameters( stream ); + Array z( make_cse( Function( programatic_name( p.amp.name()) + "_wParams", {event} ) ), size ); INFO( p.decayDescriptor() << " coupling = " << p.coupling() ); for( unsigned int j = 0 ; j < size; ++j ){ expressions[j] = expressions[j] + p.coupling() * z[j]; @@ -435,7 +435,7 @@ void PolarisedSum::transferParameters() if( m_probExpression.isLinked() ) m_probExpression.prepare(); for(auto& me : m_matrixElements){ me.coefficient = me.coupling(); - me.pdf.prepare(); + me.amp.prepare(); } for(auto& p : m_pVector ) p.update(); } From f5f1edcab711d564477c29ffa5d9ed5de2f99d78 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 23 Aug 2019 14:24:11 +0200 Subject: [PATCH 088/250] Fix missing headers in Pade --- AmpGen/CoherentSum.h | 18 ++-- AmpGen/EventList.h | 13 +-- AmpGen/Integrator.h | 31 +++--- AmpGen/Integrator2.h | 213 +++++++++++++++++++++--------------------- AmpGen/Pade.h | 9 +- AmpGen/PolarisedSum.h | 40 ++++---- src/CoherentSum.cpp | 22 +++-- src/EventList.cpp | 6 ++ src/PolarisedSum.cpp | 4 +- 9 files changed, 181 insertions(+), 175 deletions(-) diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index ead5946fd55..4fa87709798 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -61,16 +61,16 @@ namespace AmpGen real_t norm() const; real_t getNorm( const Bilinears& normalisations ); - complex_t norm( const unsigned int& x, const unsigned int& y ) const; + complex_t norm( const size_t& x, const size_t& y ) const; complex_t getVal( const Event& evt ) const; - complex_t getVal( const Event& evt, const std::vector& cacheAddresses ) const; + complex_t getVal( const Event& evt, const std::vector& cacheAddresses ) const; complex_t getValNoCache( const Event& evt ) const; complex_t getValNoCache( const Event& evt, const size_t& offset ) const; void transferParameters(); void prepare(); void printVal( const Event& evt ); - void updateNorms( const std::vector& changedPdfIndices ); + void updateNorms( const std::vector& changedPdfIndices ); void setWeight( const double& weight ) { m_weight = weight; } void setWeight( MinuitParameter* param ) { m_weightParam = param; } void makeTotalExpression(); @@ -80,7 +80,7 @@ namespace AmpGen void debug( const Event& evt, const std::string& nameMustContain=""); void generateSourceCode( const std::string& fname, const double& normalisation = 1, bool add_mt = false ); - std::vector cacheAddresses( const EventList& evts ) const; + std::vector cacheAddresses( const EventList& evts ) const; std::vector fitFractions( const LinearErrorPropagator& linProp ); std::vector> matrixElements() const { return m_matrixElements; } @@ -90,9 +90,9 @@ namespace AmpGen protected: typedef Integrator<10> integrator; std::vector> m_matrixElements; ///< Vector of (expanded) matrix elements - Bilinears m_normalisations; ///< Normalisation integrals - AmplitudeRules m_protoAmplitudes; ///< Proto amplitudes from user rule-set - integrator m_integrator; ///< Integral dispatch tool (with default unroll = 10) + Bilinears m_normalisations; ///< Normalisation integrals + AmplitudeRules m_protoAmplitudes; ///< Proto amplitudes from user rule-set + integrator m_integrator; ///< Integral dispatch tool (with default unroll = 10) TransitionMatrix m_total; ///< Total Matrix Element EventList* m_events = {nullptr}; ///< Data events to evaluate PDF on EventType m_evtType; ///< Final state for this amplitude @@ -105,8 +105,8 @@ namespace AmpGen bool m_isConstant = {false}; ///< Flag for a constant PDF bool m_dbThis = {false}; ///< Flag to generate amplitude level debugging bool m_verbosity = {false}; ///< Flag for verbose printing - std::string m_objCache = {""}; ///< Directory that contains (cached) amplitude objects - std::string m_prefix = {""}; ///< Prefix for matrix elements + std::string m_objCache = {""}; ///< Directory that contains (cached) amplitude objects + std::string m_prefix = {""}; ///< Prefix for matrix elements void addMatrixElement( std::pair& particleWithCoupling, const MinuitParameterSet& mps ); }; } // namespace AmpGen diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 709fd40eaa6..37de375eada 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -101,23 +101,13 @@ namespace AmpGen WARNING("Cache index " << size << " exceeds cache size = " << at(0).cacheSize() << " resizing to " << size + expression_size ); - - for (auto& evt : *this) evt.resizeCache( size + expression_size ); + resizeCache( size + expression_size ); } m_pdfIndex[key] = m_lastCachePosition; m_lastCachePosition += expression_size; return size; } } - - template - unsigned int extendEvent( const std::string& name, FUNCTOR func ) - { - unsigned int index = this->begin()->size(); - for ( auto& evt : *this ) evt.extendEvent(func(evt)); - m_extensions[name] = index; - return index; - } template void updateCache( const FCN& fcn, const size_t& index ) @@ -130,6 +120,7 @@ namespace AmpGen } } void reserveCache(const size_t& index); + void resizeCache(const size_t& newCacheSize ); TH1D* makeProjection(const Projection& projection , const ArgumentPack& args = ArgumentPack()) const; TH2D* makeProjection(const Projection2D& projection, const ArgumentPack& args = ArgumentPack()) const; std::vector makeProjections( const std::vector& projections, const ArgumentPack& args ); diff --git a/AmpGen/Integrator.h b/AmpGen/Integrator.h index eb8437ec05a..92c8fe760e6 100644 --- a/AmpGen/Integrator.h +++ b/AmpGen/Integrator.h @@ -41,21 +41,22 @@ namespace AmpGen void resize(const size_t& r, const size_t& c = 1 ); }; - template struct Integral { - typedef std::function TransferFCN; - size_t i = {0}; - size_t j = {0}; - TransferFCN transfer; - Integral() = default; - Integral(const size_t& i, const size_t& j, TransferFCN t) : i(i), j(j), transfer(t) {} - }; + template struct Integral + { + typedef std::function TransferFCN; + size_t i = {0}; + size_t j = {0}; + TransferFCN transfer; + Integral() = default; + Integral(const size_t& i, const size_t& j, TransferFCN t) + : i(i), j(j), transfer(t) {} + }; template class Integrator { private: typedef const complex_t& arg; - typedef std::function TransferFCN; size_t m_counter = {0}; std::array, NROLL> m_integrals; EventList* m_events = {nullptr}; @@ -91,10 +92,10 @@ namespace AmpGen EventList& events() { return *m_events; } const EventList& events() const { return *m_events; } template - void addIntegral( const T1& f1, const T2& f2, const TransferFCN& tFunc ) - { - addIntegralKeyed( m_events->getCacheIndex(f1), m_events->getCacheIndex(f2), tFunc ); - } + void addIntegral( const T1& f1, const T2& f2, const Integral::TransferFCN& tf ) + { + addIntegralKeyed( m_events->getCacheIndex(f1), m_events->getCacheIndex(f2), tf ); + } void queueIntegral(const size_t& i, const size_t& j, complex_t* result){ addIntegralKeyed(i, j, [result](arg& val){ *result = val ; } ); } @@ -113,9 +114,9 @@ namespace AmpGen else addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ out->set(i,j,val); } ); } - void addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ) + void addIntegralKeyed(const size_t& c1, const size_t& c2, const Integral::TransferFCN& tf ) { - m_integrals[m_counter++] = Integral(c1,c2,tFunc); + m_integrals[m_counter++] = Integral(c1, c2, tf); if ( m_counter == NROLL ) calculate(); } diff --git a/AmpGen/Integrator2.h b/AmpGen/Integrator2.h index dd2900f654d..212cfef4f13 100644 --- a/AmpGen/Integrator2.h +++ b/AmpGen/Integrator2.h @@ -5,120 +5,121 @@ namespace AmpGen { - template - class Integrator2 - { - private: - typedef const complex_t& arg; - typedef std::function TransferFCN; - size_t m_counter = {0}; - std::array, NROLL> m_integrals; - EventList* m_events = {nullptr}; - std::vector> m_buffer; - std::vector m_weight; - std::map m_index; - void integrateBlock() + class Integrator2 + { + private: + static constexpr size_t N = 10; + typedef const complex_t& arg; + typedef std::function TransferFCN; + size_t m_counter = {0}; + std::array, N> m_integrals; + EventList* m_events = {nullptr}; + std::vector> m_buffer; + std::vector m_weight; + std::map m_index; + void integrateBlock() + { + real_t re[N] = {0}; + real_t im[N] = {0}; + size_t addr_i[N] = {0}; + size_t addr_j[N] = {0}; + for( size_t roll = 0 ; roll < N; ++roll ) { - real_t re[NROLL] = {0}; - real_t im[NROLL] = {0}; - size_t addr_i[NROLL] = {0}; - size_t addr_j[NROLL] = {0}; - for( size_t roll = 0 ; roll < NROLL; ++roll ) - { - addr_i[roll] = m_integrals[roll].i; - addr_j[roll] = m_integrals[roll].j; - } - #pragma omp parallel for reduction(+: re, im) - for ( size_t i = 0; i < m_events->size(); ++i ) { - for ( size_t roll = 0; roll < NROLL; ++roll ) { - auto c = m_buffer[addr_i[roll]][i] * std::conj(m_buffer[addr_j[roll]][i]); - re[roll] += m_weight[i] * std::real(c); - im[roll] += m_weight[i] * std::imag(c); - } - } - real_t nv = m_events->norm(); - for ( size_t j = 0; j < m_counter; ++j ) - m_integrals[j].transfer( complex_t( re[j], im[j] ) / nv ); + addr_i[roll] = m_integrals[roll].i; + addr_j[roll] = m_integrals[roll].j; } - - public: - Integrator2( EventList* events = nullptr ) : m_events( events ){ - if( m_events != nullptr ){ - m_weight.resize( m_events->size() ); - for( size_t i = 0 ; i < m_events->size(); ++i ) - m_weight[i] = m_events->at(i).weight() / m_events->at(i).genPdf(); + #pragma omp parallel for reduction(+: re, im) + for ( size_t i = 0; i < m_events->size(); ++i ) { + for ( size_t roll = 0; roll < N; ++roll ) { + auto c = m_buffer[addr_i[roll]][i] * std::conj(m_buffer[addr_j[roll]][i]); + re[roll] += m_weight[i] * std::real(c); + im[roll] += m_weight[i] * std::imag(c); } } + real_t nv = m_events->norm(); + for ( size_t j = 0; j < m_counter; ++j ) + m_integrals[j].transfer( complex_t( re[j], im[j] ) / nv ); + m_counter = 0; + } - double sampleNorm() { return m_events->norm(); } - bool isReady() const { return m_events != nullptr; } - EventList& events() { return *m_events; } - const EventList& events() const { return *m_events; } - void queueIntegral(const size_t& c1, - const size_t& c2, - const size_t& i, - const size_t& j, - Bilinears* out, - const bool& sim = true) - { - if( ! out->workToDo(i,j) )return; - if( sim ) - addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ - out->set(i,j,val); - if( i != j ) out->set(j,i, std::conj(val) ); } ); - else - addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ out->set(i,j,val); } ); - } - void addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ) - { - m_integrals[m_counter++] = Integral(c1,c2,tFunc); - if ( m_counter == NROLL ){ integrateBlock(), m_counter = 0; } - } - void queueIntegral(const size_t& i, const size_t& j, complex_t* result){ - addIntegralKeyed(i, j, [result](arg& val){ *result = val ; } ); - } - void flush() - { - if ( m_counter == 0 ) return; - integrateBlock(); - m_counter =0; - } - template - size_t getCacheIndex(const EXPRESSION& expression) const { - return m_index.find(expression.name())->second; - } - template - void prepareExpression( const EXPRESSION& expression, const size_t& size_of = 0 ) - { - if( m_events == nullptr ) return; - size_t expression_size = size_of == 0 ? expression.returnTypeSize() / sizeof(complex_t) : size_of; - auto it = m_index.find( expression.name() ); - auto index = 0; - if( it == m_index.end() ) - { - index = m_buffer.size(); - m_index[ expression.name() ] = index; - m_buffer.resize(index+expression_size); - for(size_t j = 0 ; j != expression_size; ++j ) - m_buffer[index+j].resize( m_events->size() ); - } - else index = it->second; - #ifdef _OPENMP - #pragma omp parallel for - #endif - for ( size_t i = 0; i < m_events->size(); ++i ){ - auto v = expression(m_events->at(i).address()); - setBuffer( &(m_buffer[index][i]), v, expression_size ); - } - } - void setBuffer( complex_t* pos, const complex_t& value, const size_t& size ) + public: + Integrator2( EventList* events = nullptr ) : m_events( events ) + { + if( m_events == nullptr ) return; + m_weight.resize( m_events->size() ); + for( size_t i = 0 ; i < m_events->size(); ++i ) + m_weight[i] = m_events->at(i).weight() / m_events->at(i).genPdf(); + } + + double sampleNorm() { return m_events->norm(); } + bool isReady() const { return m_events != nullptr; } + EventList& events() { return *m_events; } + const EventList& events() const { return *m_events; } + void queueIntegral(const size_t& c1, + const size_t& c2, + const size_t& i, + const size_t& j, + Bilinears* out, + const bool& sim = true) + { + if( !out->workToDo(i,j) ) return; + if( sim ) + addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ + out->set(i,j,val); + if( i != j ) out->set(j,i, std::conj(val) ); } ); + else + addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ out->set(i,j,val); } ); + } + void addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ) + { + m_integrals[m_counter++] = Integral(c1,c2,tFunc); + if ( m_counter == N ) integrateBlock(); + } + void queueIntegral(const size_t& i, const size_t& j, complex_t* result) + { + addIntegralKeyed(i, j, [result](arg& val){ *result = val ; } ); + } + void flush() + { + if ( m_counter == 0 ) return; + integrateBlock(); + } + template size_t getCacheIndex(const T& expression) const + { + return m_index.find(expression.name())->second; + } + template void prepareExpression( const T& expression, const size_t& size_of = 0 ) + { + if( m_events == nullptr ) return; + size_t vsize = size_of == 0 ? expression.returnTypeSize() / sizeof(complex_t) : size_of; + auto it = m_index.find( expression.name() ); + auto index = 0; + if( it == m_index.end() ) { - *pos = value; + index = m_buffer.size(); + m_index[ expression.name() ] = index; + m_buffer.resize(index+vsize); + for(size_t j = 0 ; j != vsize; ++j ) + m_buffer[index+j].resize( m_events->size() ); } - void setBuffer( complex_t* pos, const std::vector& value, const size_t& size) + else index = it->second; + #ifdef _OPENMP + #pragma omp parallel for + #endif + for ( size_t i = 0; i < m_events->size(); ++i ) { - memcpy( pos, &(value[0]), size * sizeof(complex_t) ); + auto v = expression(m_events->at(i).address()); + setBuffer( &(m_buffer[index][i]), v, vsize ); } - }; + } + void setBuffer( complex_t* pos, const complex_t& value, const size_t& size ) + { + *pos = value; + } + void setBuffer( complex_t* pos, const std::vector& value, const size_t& size) + { + memcpy( pos, &(value[0]), size * sizeof(complex_t) ); + } + }; } #endif diff --git a/AmpGen/Pade.h b/AmpGen/Pade.h index d18e69a681c..7a528fa10a8 100644 --- a/AmpGen/Pade.h +++ b/AmpGen/Pade.h @@ -3,6 +3,7 @@ #include #include +#include namespace AmpGen { enum Strategy { linear, quadratic, cubic, quartic }; @@ -13,7 +14,7 @@ namespace AmpGen { const Strategy& strat = Strategy::linear); } - template class Pade + template class Pade { public: Pade(const std::function& fcn, @@ -23,8 +24,8 @@ namespace AmpGen { m_function(fcn), min(min),max(max) { auto r = detail::solve_pade(fcn, min, max, N, strat ); - for(size_t i = 0; i <= N; ++i ) co_f[i] = r[i]; - for(size_t i = 0; i < N; ++i ) co_g[i] = r[i+(N+1)]; + for(unsigned i = 0; i <= N; ++i ) co_f[i] = r[i]; + for(unsigned i = 0; i < N; ++i ) co_g[i] = r[i+(N+1)]; range = 1./(max-min); } T operator()(const T& s) @@ -33,7 +34,7 @@ namespace AmpGen { T f = 0; T g = 1; T acc = 1; - for(size_t i = 0; i < N; ++i){ + for(unsigned i = 0; i < N; ++i){ f += co_f[i] * acc; acc *= x; g += co_g[i] * acc; diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index 7c8b240ee41..0ce4fa3b580 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -35,28 +35,30 @@ namespace AmpGen class PolarisedSum { public: + typedef Integrator<10> integrator; + PolarisedSum() = default; - PolarisedSum( const EventType& eventType, AmpGen::MinuitParameterSet& mps, const std::string& prefix="" ); + PolarisedSum(const EventType&, AmpGen::MinuitParameterSet&, const std::string& = ""); void prepare(); - void setEvents( AmpGen::EventList& events ); - void setMC( AmpGen::EventList& events ); - void reset( const bool& flag = false ); - void debug(const AmpGen::Event& event ); + void setEvents(AmpGen::EventList&); + void setMC(AmpGen::EventList&); + void reset(const bool& = false); + void debug(const AmpGen::Event&); void debug_norm(); - void setWeight( MinuitParameter* param ); + void setWeight(MinuitParameter*); double getWeight() const; - void calculateNorms(const std::vector& hasChanged); - void generateSourceCode( const std::string& fname, const double& normalisation = 1, bool add_mt = false ); + void calculateNorms(const std::vector&); + void generateSourceCode(const std::string&, const double& = 1, bool = false); void build_probunnormalised(); - Expression probExpression( const Tensor& T_matrix, const std::vector& p, DebugSymbols* = nullptr ) const; - size_t size() const ; + Expression probExpression(const Tensor&, const std::vector&, DebugSymbols* = nullptr) const; + size_t size() const; real_t norm() const; - complex_t norm(const size_t& i, const size_t& j, Integrator2<18>* integ = nullptr ); - inline real_t operator()(const AmpGen::Event& event) const { return m_weight * prob_unnormalised(event) / m_norm; } - real_t prob_unnormalised( const AmpGen::Event& evt ) const; - real_t prob(const AmpGen::Event& evt ) const ; - real_t getValNoCache( const AmpGen::Event& evt ) ; - std::vector fitFractions( const LinearErrorPropagator& prop ); + complex_t norm(const size_t&, const size_t&, integrator* = nullptr); + inline real_t operator()(const AmpGen::Event& evt) const { return m_weight * prob_unnormalised(evt) / m_norm; } + real_t prob_unnormalised(const AmpGen::Event&) const; + real_t prob(const AmpGen::Event&) const; + real_t getValNoCache(const AmpGen::Event&) ; + std::vector fitFractions(const LinearErrorPropagator&); std::vector>> matrixElements() const; void transferParameters(); Tensor transitionMatrix(); @@ -72,7 +74,7 @@ namespace AmpGen std::vector m_pVector = {}; bool m_verbosity = {0}; bool m_debug = {0}; - Integrator2<18> m_integrator; + integrator m_integrator; std::vector m_norms; std::vector> m_polStates; EventType m_eventType; @@ -82,8 +84,8 @@ namespace AmpGen std::vector>> m_matrixElements; CompiledExpression m_probExpression; AmplitudeRules m_rules; - std::vector> polarisationOuterProduct( const std::vector>& A, const std::vector& B ) const; - std::vector polarisations( const std::string& name ) const ; + std::vector> polarisationOuterProduct(const std::vector>&, const std::vector&) const; + std::vector polarisations(const std::string&) const ; }; } // namespace AmpGen diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index e289a5717a3..f531ef25201 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -61,7 +61,7 @@ void CoherentSum::prepare() if ( m_weightParam != nullptr ) m_weight = m_weightParam->mean(); if ( m_isConstant && m_prepareCalls != 0 ) return; transferParameters(); - std::vector changedPdfIndices; + std::vector changedPdfIndices; ProfileClock clockEval; bool printed = false; for ( size_t i = 0; i < m_matrixElements.size(); ++i ) { @@ -70,11 +70,15 @@ void CoherentSum::prepare() if ( m_prepareCalls != 0 && !amp.hasExternalsChanged() ) continue; ProfileClock clockThisElement; if ( m_events != nullptr ) { - if ( m_matrixElements[i].addressData == 999 ) + if ( m_matrixElements[i].addressData == 999 ){ + if( m_events->at(0).cacheSize() <= m_matrixElements.size()) + m_events->resizeCache( m_matrixElements.size() ); m_matrixElements[i].addressData = m_events->registerExpression( amp ); + } m_events->updateCache( amp, m_matrixElements[i].addressData ); } else if ( i == 0 && m_verbosity ) WARNING( "No data events specified for " << this ); + m_integrator.prepareExpression( m_matrixElements[i].amp ); clockThisElement.stop(); if ( m_verbosity && ( m_prepareCalls > m_lastPrint + m_printFreq || m_prepareCalls == 0 ) ) { INFO( amp.name() << " (t = " << clockThisElement << " ms, nCalls = " << m_prepareCalls << ", events = " << m_events->size() << ")" ); @@ -99,9 +103,9 @@ void CoherentSum::prepare() m_prepareCalls++; } -void CoherentSum::updateNorms( const std::vector& changedPdfIndices ) +void CoherentSum::updateNorms( const std::vector& changedPdfIndices ) { - for ( auto& i : changedPdfIndices ) m_integrator.prepareExpression( m_matrixElements[i].amp ); + //for ( auto& i : changedPdfIndices ) m_integrator.prepareExpression( m_matrixElements[i].amp ); std::vector cacheIndex; std::transform( m_matrixElements.begin(), m_matrixElements.end(), std::back_inserter(cacheIndex), [this](auto& m){ return this->m_integrator.getCacheIndex( m.amp ) ; } ); @@ -315,7 +319,7 @@ real_t CoherentSum::norm(const Bilinears& norms) const return acc.real(); } -complex_t CoherentSum::norm(const unsigned int& x, const unsigned int& y) const +complex_t CoherentSum::norm(const size_t& x, const size_t& y) const { return m_normalisations.get(x, y); } @@ -339,9 +343,9 @@ void CoherentSum::printVal(const Event& evt) } } -std::vector CoherentSum::cacheAddresses( const EventList& evts ) const +std::vector CoherentSum::cacheAddresses( const EventList& evts ) const { - std::vector addresses; + std::vector addresses; std::transform( m_matrixElements.begin(), m_matrixElements.end(), std::back_inserter(addresses), [&evts](auto& it ){ return evts.getCacheIndex( it.amp ) ; } ); return addresses; @@ -356,10 +360,10 @@ complex_t CoherentSum::getVal( const Event& evt ) const return value; } -complex_t CoherentSum::getVal( const Event& evt, const std::vector& cacheAddresses ) const +complex_t CoherentSum::getVal( const Event& evt, const std::vector& cacheAddresses ) const { complex_t value( 0., 0. ); - for ( unsigned int i = 0; i < m_matrixElements.size(); ++i ) + for ( size_t i = 0; i < m_matrixElements.size(); ++i ) value += m_matrixElements[i].coefficient * evt.getCache( cacheAddresses[i] ); return value; } diff --git a/src/EventList.cpp b/src/EventList.cpp index 4ae200ce39a..5b6c01310ac 100644 --- a/src/EventList.cpp +++ b/src/EventList.cpp @@ -263,3 +263,9 @@ void EventList::reserveCache(const size_t& size) if ( size >= at(0).cacheSize() ) for (auto& evt : *this) evt.resizeCache(evt.cacheSize() + size); } + +void EventList::resizeCache(const size_t& newCacheSize ) +{ + for (auto& evt : *this) evt.resizeCache( newCacheSize ); +} + diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 44962f24a99..5302abdc784 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -213,7 +213,7 @@ void PolarisedSum::setEvents( EventList& events ) void PolarisedSum::setMC( EventList& events ) { m_nCalls = 0; - m_integrator = Integrator2<18>(&events); + m_integrator = integrator(&events); } size_t PolarisedSum::size() const @@ -260,7 +260,7 @@ double PolarisedSum::norm() const return m_norm; } -complex_t PolarisedSum::norm(const size_t& i, const size_t& j, Integrator2<18>* integ) +complex_t PolarisedSum::norm(const size_t& i, const size_t& j, AmpGen::PolarisedSum::integrator* integ) { auto ai = m_integIndex[i]; auto aj = m_integIndex[j]; From 01d869ab8789d54537d21669a81be6f62cc74c12 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 23 Aug 2019 14:37:52 +0200 Subject: [PATCH 089/250] fixed in pade... --- AmpGen/Pade.h | 1 + src/Pade.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/AmpGen/Pade.h b/AmpGen/Pade.h index 7a528fa10a8..2b3c7d90d3d 100644 --- a/AmpGen/Pade.h +++ b/AmpGen/Pade.h @@ -11,6 +11,7 @@ namespace AmpGen { std::vector solve_pade(const std::function& fcn, const double& min, const double& max, + const unsigned& N, const Strategy& strat = Strategy::linear); } diff --git a/src/Pade.cpp b/src/Pade.cpp index aa57158a7fa..40a8e697778 100644 --- a/src/Pade.cpp +++ b/src/Pade.cpp @@ -6,25 +6,25 @@ std::vector AmpGen::detail::solve_pade(const std::function& fcn, const double& min, const double& max, - const int& N, - const AmpGen::Strategy& strat = AmpGen::Strategy::linear) + const unsigned& N, + const AmpGen::Strategy& strat) { TMatrixD solver(2*N+1,2*N+1); std::vector samples(2*N+1); if( strat < 4 ){ - for(size_t eq = 0 ; eq < 2*N+1; ++eq) + for(unsigned eq = 0 ; eq < 2*N+1; ++eq) samples[eq] = pow( eq/double(2*N), strat + 1); } TVectorD rest(2*N+1); - for( int eq = 0 ; eq < 2*N+1; ++eq ){ + for( unsigned eq = 0 ; eq < 2*N+1; ++eq ){ rest(eq) = fcn( samples[eq]*(max-min) + min); - for(int i = 0; i <= N; ++i) solver(eq,i) = pow(samples[eq],i); - for(int i = 1; i <= N; ++i) solver(eq,i+N) = -rest(eq)* pow(samples[eq],i); + for(unsigned i = 0; i <= N; ++i) solver(eq,i) = pow(samples[eq],i); + for(unsigned i = 1; i <= N; ++i) solver(eq,i+N) = -rest(eq)* pow(samples[eq],i); } solver.Invert(); auto r = solver * rest; std::vector rv(2*N+1); - for( size_t i =0;i<2*N+1;++i) rv[i] = r[i]; + for(unsigned i = 0; i<2*N+1; ++i) rv[i] = r[i]; return rv; } From 49fcc6f155e5680393a613c1b6754889f1ebc475 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 27 Aug 2019 13:02:50 +0200 Subject: [PATCH 090/250] Fix binned integrator to match CoherentSum, fix tests in ExpressionParser under clang --- AmpGen/Integrator.h | 4 ++-- test/test_ExpressionParser.cpp | 23 ++++++++++++----------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/AmpGen/Integrator.h b/AmpGen/Integrator.h index 92c8fe760e6..7f16be8d0f8 100644 --- a/AmpGen/Integrator.h +++ b/AmpGen/Integrator.h @@ -248,7 +248,7 @@ namespace AmpGen std::vector toUpdate; std::vector integralHasChanged( size * size ); for ( size_t x = 0; x < size; ++x ) { - auto& pdf = mE[x].pdf; + auto& pdf = mE[x].amp; pdf.prepare(); if ( !pdf.hasExternalsChanged() ) continue; m_events->updateCache( pdf, m_events->getCacheIndex( pdf ) ); @@ -261,7 +261,7 @@ namespace AmpGen integralHasChanged[i * size + j] = true; integralHasChanged[j * size + i] = true; - addIntegral( mE[i].pdf, mE[j].pdf, + addIntegral( mE[i].amp, mE[j].amp, [i, j, &normalisations]( const auto& val ) { for ( unsigned int bin = 0; bin < NBINS; ++bin ) { normalisations[bin].set( i, j, val[bin] ); diff --git a/test/test_ExpressionParser.cpp b/test/test_ExpressionParser.cpp index f2822eebbf7..d6657a1c6c0 100644 --- a/test/test_ExpressionParser.cpp +++ b/test/test_ExpressionParser.cpp @@ -3,11 +3,12 @@ #define BOOST_TEST_MODULE "ExpressionParser" #include -namespace utf = boost::unit_test; #include "AmpGen/ExpressionParser.h" #include "AmpGen/MinuitParameterSet.h" +namespace utf = boost::unit_test; +namespace tt = boost::test_tools; using namespace AmpGen; BOOST_AUTO_TEST_CASE( simple_numericalExpressions ){ @@ -59,16 +60,16 @@ BOOST_AUTO_TEST_CASE( parametericExpressions ) { } return std::real( ExpressionParser::parse(newLine, &mps)() ); }; - BOOST_CHECK( test("a+(cos(b-sin(2/a*pi))-sin(a-cos(2*b/pi)))-b") == a+(cos(b-sin(2/a*pi))-sin(a-cos(2*b/pi)))-b ); - BOOST_CHECK( test("sin(a)+sin(b)") == sin(a)+sin(b) ); - BOOST_CHECK( test("abs(sin(sqrt(a^2+b^2))*255)") == abs(sin(sqrt(a*a+b*b))*255) ); - BOOST_CHECK( test("sqrt(a) Date: Thu, 29 Aug 2019 16:10:12 +0200 Subject: [PATCH 091/250] Update mass_width.csv --- options/mass_width.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/mass_width.csv b/options/mass_width.csv index 75322a24e3c..247496857bd 100644 --- a/options/mass_width.csv +++ b/options/mass_width.csv @@ -16,7 +16,7 @@ * A1. read table into any spreadsheet or database program that accepts a comma-separated format * A2. For example, in EXCEL, open a blank workbook and import this file as external data, * comma-delimited, starting the import at row 100, which contains column header names. -* B1. In a FORTRAN program, ignore documentation lines that begin with "*" and process data lines using +* B1. In a FORTRAN program, ignore documentation lines that begin with '*' and process data lines using * FORMAT (BN, E14.0, 1X, 2(E7.0, 1X), E12.0, 1X, 2(E7.0, 1X), A3, 1X, A1, 1X, A4, 1X, 3(A1, 1X), A7, 1X, A4, 1X, 2(A1, 1X), A17, 1X, A) * B2. WARNING. MINUS VALUE OF ERROR means its absence! * B3. columns contents Fortran I/O From 4478134feef9c3ac02d551b7775d5a2f8e7a7742 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 29 Aug 2019 16:11:15 +0200 Subject: [PATCH 092/250] Update mass_width.csv --- options/mass_width.csv | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/options/mass_width.csv b/options/mass_width.csv index 247496857bd..61963edd964 100644 --- a/options/mass_width.csv +++ b/options/mass_width.csv @@ -51,7 +51,7 @@ * with ascii name formed by concatenation of the name shown below with charge * ( e- <--> e+, pi+ <--> pi-, K+ <--> K-, W+ <--> W- ). * A = F - particle that has anti-particle partner different from particle -* with ascii name formed by concatenation of the name shown below with string "bar" and charge +* with ascii name formed by concatenation of the name shown below with string 'bar' and charge * by the rule (nu(e) <--> nubar(e), p <--> pbar, Delta++ <--> Deltabar--) * A = blank - particle that coincide with its antiparticle (gamma, pi0, eta). * 85 comma (1X) @@ -59,7 +59,7 @@ * The number used in the PDG Monte Carlo numbering scheme (see RPP). * Only particles are shown in this table and they are given positive ID numbers. * For antiparticles, change the ID to negative. Thus pi- has code -211. -* The ID has up to 7 digits. See RPP "Monte Carlo particle numbering scheme" +* The ID has up to 7 digits. See RPP 'Monte Carlo particle numbering scheme' * for details. * 94 comma (1X) * 95 - 99 charge (A4) @@ -81,7 +81,7 @@ * space even though they are well established. * S - The particle is omitted from the particle properties Summary Tables * because it is not well established. -* F - Special case: "Further mesons", see RPP , these states are in the RPP +* F - Special case: 'Further mesons', see RPP , these states are in the RPP * database but are poorly established or observed by a single group and thus * need confirmation. If used, these should be referred to the original publication. * For these states we list a single line without charge and with C-parity, if known, @@ -91,10 +91,10 @@ * 105 -122 particle name (A17) * 123 comma (1X) * 124 -139 Quark contents (A) -* Note: capital letters represents anti-quarks, "qQ" stands for light quark, light +* Note: capital letters represents anti-quarks, 'qQ' stands for light quark, light * anti-quark pair with unknown wave functions. * x, y - wave function coefficients, see RPP 'Quark Model' Review -* p, q - CP violation parameters, See. RPP "CP violation in KL Decays" review. +* p, q - CP violation parameters, See. RPP 'CP violation in KL Decays' review. * * *MASS(MeV) ,Err+ ,Err- ,WIDTH(MeV) ,Err+ ,Err- ,I ,G,J ,P,C,A,PDG-MC ,Chrg,R,S,Name ,Quarks From 68767c72252d48869b1c1a4a6fa86b5d259d87cd Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 2 Sep 2019 20:43:41 +0200 Subject: [PATCH 093/250] Cache some coordinates transforms in order to make deeper decay processes tractable --- AmpGen/ASTResolver.h | 3 -- AmpGen/CoherentSum.h | 3 +- AmpGen/Minimiser.h | 44 +++++++++++++++++----- AmpGen/Transform.h | 6 ++- AmpGen/Wigner.h | 32 ++++++++-------- src/ASTResolver.cpp | 38 +++++++------------ src/CoherentSum.cpp | 43 ++++++++++------------ src/CompiledExpressionBase.cpp | 5 ++- src/Minimiser.cpp | 20 +++++++++- src/Particle.cpp | 3 +- src/PolarisedSum.cpp | 38 ++++++++++--------- src/Transform.cpp | 15 +++++--- src/Wigner.cpp | 67 +++++++++++++++++----------------- 13 files changed, 177 insertions(+), 140 deletions(-) diff --git a/AmpGen/ASTResolver.h b/AmpGen/ASTResolver.h index 839c3991fab..3b52df3416d 100644 --- a/AmpGen/ASTResolver.h +++ b/AmpGen/ASTResolver.h @@ -29,8 +29,6 @@ namespace AmpGen { { public: ASTResolver(const std::map& evtMap = {} , const MinuitParameterSet* mps = nullptr ); - bool hasSubExpressions() const; - void reduceSubTrees(); void cleanup(); std::vector> getOrderedSubExpressions( const Expression& expression); @@ -59,7 +57,6 @@ namespace AmpGen { std::map m_parameterMapping; /// Mapping of parameters to compile parameters const MinuitParameterSet* m_mps; /// Set of MinuitParameters std::map m_tempTrees; /// temporary store of sub-trees for performing cse reduction - std::map m_subTrees; /// Unordered sub-trees unsigned int m_nParameters; /// Number of parameters bool m_enable_cuda; /// flag to generate CUDA code <> bool m_enable_compileTimeConstants; /// flag to enable compile time constants <> diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index 4fa87709798..740ea2b637e 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -19,6 +19,7 @@ #include "AmpGen/Types.h" #include "AmpGen/Event.h" #include "AmpGen/Projection.h" +//#include "AmpGen/functional/pdf.h" namespace AmpGen { @@ -39,7 +40,7 @@ namespace AmpGen where @f$\mathcal{P}(\psi)@f$ is the probability, @f$g_i@f$ is the coupling to an isobar channel, and @f$\mathcal{A}_i(\psi)@f$ is the amplitude of the ith channel. */ - class CoherentSum + class CoherentSum // : public functional::pdf_base { public: CoherentSum(); diff --git a/AmpGen/Minimiser.h b/AmpGen/Minimiser.h index ea48dbcd40c..b66de44df39 100644 --- a/AmpGen/Minimiser.h +++ b/AmpGen/Minimiser.h @@ -13,9 +13,9 @@ /** @cond PRIVATE */ namespace ROOT { - namespace Math + namespace Minuit2 { - class Minimizer; + class Minuit2Minimizer; } } class TGraph; @@ -30,14 +30,37 @@ namespace AmpGen class Minimiser { + private: + template + struct Has + { + typedef char YesType[1]; + typedef char NoType[2]; + template static YesType& test( decltype(&C::getVal) ) ; + template static NoType& test(...); + enum { value = sizeof(test(0)) == sizeof(YesType) }; + }; + + + public: - template + template typename std::enable_if_t::value, void> setFunction( TYPE& fcn ) + { + m_theFunction = [&fcn]() { return fcn.getVal(); }; + } + template typename std::enable_if_t::value, void> setFunction(TYPE& fcn) + { + m_theFunction = [&fcn](){ return fcn() ; } ; + } + + template Minimiser(TYPE& fitFunction, MinuitParameterSet* mps) : m_parSet(mps) { - m_theFunction = [&fitFunction]() { return fitFunction.getVal(); }; + setFunction(fitFunction); prepare(); } + Minimiser(std::function& fitFunction, MinuitParameterSet* mps) : m_parSet(mps), m_theFunction(fitFunction) @@ -48,6 +71,7 @@ namespace AmpGen unsigned int nPars() const; void prepare(); + void gradientTest(); bool doFit(); TGraph* scan( MinuitParameter* param, const double& min, const double& max, const double& step ); void addExtendedTerm( IExtendLikelihood* term ); @@ -57,21 +81,21 @@ namespace AmpGen double FCN() const; MinuitParameterSet* parSet() const; int status() const; - ROOT::Math::Minimizer* minimiserInternal(); + ROOT::Minuit2::Minuit2Minimizer* minimiserInternal(); private: - MinuitParameterSet* m_parSet = {nullptr}; + MinuitParameterSet* m_parSet = {nullptr}; std::function m_theFunction; - ROOT::Math::Minimizer* m_minimiser = {nullptr}; - std::vector m_covMatrix = {0}; - std::vector m_mapping; - std::vector m_extendedTerms; + ROOT::Minuit2::Minuit2Minimizer* m_minimiser = {nullptr}; + std::vector m_covMatrix = {0}; + std::vector m_mapping = {}; int m_status = {0}; unsigned int m_nParams = {0}; unsigned int m_lastPrint = {0}; unsigned int m_printLevel = {0}; double m_ll_zero = {0}; bool m_normalise = {false}; + std::vector m_extendedTerms; }; } // namespace AmpGen #endif diff --git a/AmpGen/Transform.h b/AmpGen/Transform.h index 576e56e987c..0bf87a5edfb 100644 --- a/AmpGen/Transform.h +++ b/AmpGen/Transform.h @@ -43,9 +43,9 @@ namespace AmpGen { public: TransformSequence() = default; TransformSequence inverse() const; - Tensor operator()( const Transform::Representation& repr ) const; + Tensor operator()( const Transform::Representation& repr ); Tensor operator()( const Tensor& tensor, - const Transform::Representation& repr=Transform::Representation::Vector ) const; + const Transform::Representation& repr=Transform::Representation::Vector ); void add( const Transform& transform ); void add( const TransformSequence& transform ); void stepThrough( const Tensor& tensor, @@ -60,7 +60,9 @@ namespace AmpGen { std::vector::iterator end() { return m_transforms.end(); } private: std::vector m_transforms; + std::array m_cache; }; + } #endif diff --git a/AmpGen/Wigner.h b/AmpGen/Wigner.h index 18dbe8ec5d6..cd6c4a7aec5 100644 --- a/AmpGen/Wigner.h +++ b/AmpGen/Wigner.h @@ -6,21 +6,20 @@ #include "AmpGen/Transform.h" namespace AmpGen { -class Particle; + class Particle; Expression wigner_d( const Expression& cb, const double& j, const double& m, const double& n ); - Expression wigner_D( const Tensor& P, const double& J, const double& lA, const double& lB, DebugSymbols* db , const std::string& name = ""); - + Expression wigner_D( const std::pair& P, const double& J, const double& lA, const double& lB, DebugSymbols* db); /** @ingroup Vertices function CG Calculates the Clebsch-Gordan coefficient for (j1 m1 j2 m2 | J M), the expansion coefficients in */ double CG( const double& j1, - const double& m1, - const double& j2, - const double& m2, - const double& J, - const double& M ); + const double& m1, + const double& j2, + const double& m2, + const double& J, + const double& M ); /** @ingroup Vertices function wickTransform Generates a wick transform sequence that aligns tensor P (four-vector) to the +/- ve z-axis, then boosts to the rest frame. @@ -29,9 +28,8 @@ class Particle; This ensures that singly and doubly primed helicity frames remain orthonormal. */ TransformSequence wickTransform(const Tensor& P, const Expression& M, const int& ve =1, const bool& handleZeroCase = false); - - Expression helicityAmplitude( const Particle& particle, const TransformSequence& parentFrame, const double& Mz, DebugSymbols* db , const int sgn=1); + Expression helicityAmplitude(const Particle& particle, TransformSequence& parentFrame, const double& Mz, DebugSymbols* db , const int sgn=1, std::map* cacheptr = nullptr); Tensor basisSpinor(const int& polState, const int& id); Tensor basisVector(const int& polState); @@ -43,14 +41,14 @@ class Particle; double m1; double m2; }; - + std::vector calculate_recoupling_constants( - const double& J, - const double& M, - const double& L, - const double& S, - const double& j1, - const double& j2 ); + const double& J, + const double& M, + const double& L, + const double& S, + const double& j1, + const double& j2 ); } #endif diff --git a/src/ASTResolver.cpp b/src/ASTResolver.cpp index 001830e25bf..8eec9f653ee 100644 --- a/src/ASTResolver.cpp +++ b/src/ASTResolver.cpp @@ -22,37 +22,26 @@ ASTResolver::ASTResolver(const std::map& evtMap, m_enable_compileTimeConstants = NamedParameter("ASTResolver::CompileTimeConstants", false); } -bool ASTResolver::hasSubExpressions() const -{ - return m_subTrees.size() != 0; -} - -void ASTResolver::reduceSubTrees() -{ - m_subTrees.clear(); - for( auto& t : m_tempTrees ){ - auto expr = t.first->m_expression; - uint64_t key = t.first->key(); - if( m_subTrees.count( key ) == 0 ){ - m_subTrees[ key ] = t.first->m_expression ; - } - } - m_tempTrees.clear(); -} - std::vector> ASTResolver::getOrderedSubExpressions( const Expression& expression ) { std::vector> subexpressions; expression.resolve( *this ); - std::map used_functions; + std::map used_functions; + std::map subTrees; do { - reduceSubTrees(); - bool verbose = false; - for( auto& st : m_subTrees ) { + subTrees.clear(); + for( auto& t : m_tempTrees ) + { + auto expr = t.first->m_expression; + uint64_t key = t.first->key(); + if( subTrees.count( key ) == 0 ) subTrees[ key ] = t.first->m_expression ; + } + INFO("Reducing subtrees: " << m_tempTrees.size() << " " << subTrees.size() ); + m_tempTrees.clear(); + for( auto& st : subTrees ){ st.second.resolve( *this ); auto stack_pos = used_functions.find( st.first ); if ( stack_pos == used_functions.end() ) { - if( verbose ) INFO("Function: " << st.first << " is at the end of stack"); subexpressions.emplace_back( st.first , st.second ); used_functions[st.first] = subexpressions.size() - 1; continue; @@ -66,7 +55,7 @@ std::vector> ASTResolver::getOrderedSubExpression } used_functions[st.first] = subexpressions.size() - 1; } - } while ( hasSubExpressions() ); + } while ( subTrees.size() !=0 ); std::reverse( subexpressions.begin(), subexpressions.end() ); return subexpressions; } @@ -162,4 +151,3 @@ std::string ASTResolver::resolvedParameter( const IExpression* param ) const return ""; } } - diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index f531ef25201..b0487ec794c 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -56,6 +56,16 @@ CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, m_isConstant = false ; } +void updateCache(EventList* events, TransitionMatrix& me, const size_t& sizeMax) +{ + if ( me.addressData == 999 ) + { + if( events->at(0).cacheSize() <= sizeMax) events->resizeCache(sizeMax); + me.addressData = events->registerExpression( me.amp ); + } + events->updateCache(me.amp, me.addressData); +} + void CoherentSum::prepare() { if ( m_weightParam != nullptr ) m_weight = m_weightParam->mean(); @@ -63,36 +73,22 @@ void CoherentSum::prepare() transferParameters(); std::vector changedPdfIndices; ProfileClock clockEval; - bool printed = false; + bool print = false; for ( size_t i = 0; i < m_matrixElements.size(); ++i ) { - auto& amp = m_matrixElements[i].amp; - amp.prepare(); - if ( m_prepareCalls != 0 && !amp.hasExternalsChanged() ) continue; - ProfileClock clockThisElement; - if ( m_events != nullptr ) { - if ( m_matrixElements[i].addressData == 999 ){ - if( m_events->at(0).cacheSize() <= m_matrixElements.size()) - m_events->resizeCache( m_matrixElements.size() ); - m_matrixElements[i].addressData = m_events->registerExpression( amp ); - } - m_events->updateCache( amp, m_matrixElements[i].addressData ); - } - else if ( i == 0 && m_verbosity ) WARNING( "No data events specified for " << this ); + m_matrixElements[i].amp.prepare(); + if ( m_prepareCalls != 0 && !m_matrixElements[i].amp.hasExternalsChanged() ) continue; + if ( m_events != nullptr ) updateCache( m_events, m_matrixElements[i], m_matrixElements.size() ); m_integrator.prepareExpression( m_matrixElements[i].amp ); - clockThisElement.stop(); - if ( m_verbosity && ( m_prepareCalls > m_lastPrint + m_printFreq || m_prepareCalls == 0 ) ) { - INFO( amp.name() << " (t = " << clockThisElement << " ms, nCalls = " << m_prepareCalls << ", events = " << m_events->size() << ")" ); - printed = true; - } changedPdfIndices.push_back(i); - amp.resetExternals(); + m_matrixElements[i].amp.resetExternals(); + print = true; } clockEval.stop(); ProfileClock clockIntegral; if ( m_integrator.isReady()) updateNorms( changedPdfIndices ); else if ( m_verbosity ) WARNING( "No simulated sample specified for " << this ); m_norm = norm(); - if ( m_verbosity && printed ) { + if ( m_verbosity && print ) { clockIntegral.stop(); INFO( "Time Performance: " << "Eval = " << clockEval << " ms" @@ -138,6 +134,7 @@ void CoherentSum::debug( const Event& evt, const std::string& nameMustContain ) std::vector CoherentSum::fitFractions(const LinearErrorPropagator& linProp) { + prepare(); bool recomputeIntegrals = NamedParameter("CoherentSum::RecomputeIntegrals", false ); std::vector outputFractions; for(auto& rule : m_protoAmplitudes.rules()) @@ -288,14 +285,14 @@ void CoherentSum::reset( bool resetEvents ) void CoherentSum::setEvents( EventList& list ) { - if ( m_verbosity ) INFO( "Setting events to size = " << list.size() << " for " << this ); + if ( m_verbosity ) INFO( "Setting event list with:" << list.size() << " events for " << this ); reset(); m_events = &list; } void CoherentSum::setMC( EventList& sim ) { - if ( m_verbosity ) INFO( "Setting MC = " << &sim << " for " << this ); + if ( m_verbosity ) INFO( "Setting norm. event list with:" << sim.size() << " events for " << this ); reset(); m_integrator = integrator(&sim); } diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index 1e71a632144..6368a5e5880 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -11,7 +11,7 @@ #include "AmpGen/ThreadPool.h" #include "AmpGen/CompilerWrapper.h" #include "AmpGen/ASTResolver.h" - +#include "AmpGen/ProfileClock.h" using namespace AmpGen; std::string AmpGen::programatic_name( std::string s ) @@ -28,6 +28,7 @@ std::string AmpGen::programatic_name( std::string s ) void CompiledExpressionBase::resolve(const MinuitParameterSet* mps) { + ProfileClock pc; if( m_resolver != nullptr ) delete m_resolver ; m_resolver = new ASTResolver( m_evtMap, mps ); m_dependentSubexpressions = m_resolver->getOrderedSubExpressions( m_obj ); @@ -45,6 +46,8 @@ void CompiledExpressionBase::resolve(const MinuitParameterSet* mps) for( auto& expression : m_resolver->cacheFunctions() ) m_cacheTransfers.emplace_back( expression.second ); resizeExternalCache( m_resolver->nParams() ); + pc.stop(); + //INFO("Took: " << pc << " ms to resolve tree"); prepare(); } diff --git a/src/Minimiser.cpp b/src/Minimiser.cpp index 136c71c8d72..c64b0ec25c5 100644 --- a/src/Minimiser.cpp +++ b/src/Minimiser.cpp @@ -37,6 +37,24 @@ double Minimiser::operator()( const double* xx ) double Minimiser::FCN() const { return m_theFunction(); } +void Minimiser::gradientTest() +{ + for (size_t i = 0; i < m_mapping.size(); ++i) { + auto parameter = m_parSet->at( m_mapping[i] ); + double m = parameter->mean(); + parameter->setCurrentFitVal( parameter->meanInit() + parameter->stepInit() ); + double vp = FCN(); + parameter->setCurrentFitVal( parameter->meanInit() - parameter->stepInit() ); + double vm = FCN(); + if ( parameter->stepInit() == 0 ) { + WARNING( "Step of free parameter: " << parameter->name() << " = 0" ); + } else { + INFO( " dF/d{" << parameter->name() << "} = " << ( vp - vm ) / ( 2 * parameter->stepInit() ) ); + } + parameter->setCurrentFitVal( m ); + } +} + void Minimiser::prepare() { std::string algorithm = NamedParameter( "Minimiser::Algorithm", "Hesse"); @@ -136,4 +154,4 @@ void Minimiser::addExtendedTerm( IExtendLikelihood* m_term ) m_extendedTerms.push_back( m_term ); } -ROOT::Math::Minimizer* Minimiser::minimiserInternal() { return m_minimiser; } +ROOT::Minuit2::Minuit2Minimizer* Minimiser::minimiserInternal() { return m_minimiser; } diff --git a/src/Particle.cpp b/src/Particle.cpp index e1471d58dca..ab538d8f6db 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -436,7 +436,8 @@ Expression Particle::getExpression( DebugSymbols* db, const unsigned int& index } } if ( includeSpin && spinFormalism == "Canonical" ){ - spinFactor = helicityAmplitude(*this, TransformSequence(), m_props->isBoson() ? polState() : double(polState())/2.0, db); + TransformSequence t = TransformSequence(); + spinFactor = helicityAmplitude(*this, t, m_props->isBoson() ? polState() : double(polState())/2.0, db); } if( db != nullptr ){ std::string finalStateString=""; diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 5302abdc784..38579628d12 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -40,7 +40,6 @@ PolarisedSum::PolarisedSum( const EventType& type, m_prefix(prefix) { m_debug = NamedParameter( "PolarisedSum::Debug" ,false ); - bool autoCompile = NamedParameter( "PolarisedSum::AutoCompile",true ); std::string objCache = NamedParameter("PolarisedSum::ObjectCache","" ); m_verbosity = NamedParameter( "PolarisedSum::Verbosity" ,0 ); m_rules = AmplitudeRules(mps); @@ -54,24 +53,29 @@ PolarisedSum::PolarisedSum( const EventType& type, for(size_t i = 0 ; i < fs.size(); ++i ) fs[i]->setPolarisationState( polState[i+1] ); }; for( auto& m : protoAmps ) INFO( m.first.uniqueString() ); - for( auto& matrix_element : protoAmps ){ - Tensor thisExpression( Tensor::dim(m_polStates.size()) ); - int i = 0 ; + m_matrixElements.resize( protoAmps.size() ); + + ThreadPool tp(8); + for(unsigned i = 0; i < m_matrixElements.size(); ++i) + { + tp.enqueue( [i,this,&mps,&protoAmps, &set_polarisation_state]{ + Tensor thisExpression( Tensor::dim(this->m_polStates.size()) ); DebugSymbols syms; - for( auto& polState : m_polStates ){ - set_polarisation_state( matrix_element, polState ); - thisExpression[i++] = make_cse( matrix_element.first.getExpression(&syms) ); + for( unsigned j=0;j , const real_t*, const real_t* > expression( - TensorExpression( thisExpression), - matrix_element.first.decayDescriptor(), - type.getEventFormat(), m_debug ? syms : DebugSymbols() ,&mps ); - m_matrixElements.emplace_back(matrix_element.first, matrix_element.second, expression ); - } - if(autoCompile){ - ThreadPool tp(8); - for( auto& me : m_matrixElements ) tp.enqueue([&]{ CompilerWrapper().compile(me.amp, objCache);}); - } + m_matrixElements[i] = TransitionMatrix>( + protoAmps[i].first, + protoAmps[i].second, + CompiledExpression< std::vector,const real_t*, const real_t*>( + TensorExpression(thisExpression), + protoAmps[i].first.decayDescriptor(), + this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,&mps ) ); + CompilerWrapper().compile( m_matrixElements[i].amp ); + }); + } + auto d = m_eventType.dim(); auto p = [&mps](const std::string& name){ return mps.addOrGet(name,2,0,0); }; if( d.first == 1 ) m_pVector = {}; diff --git a/src/Transform.cpp b/src/Transform.cpp index 4dbb48b3e33..f498eb98ef1 100644 --- a/src/Transform.cpp +++ b/src/Transform.cpp @@ -97,7 +97,7 @@ Tensor Transform::operator()(const Representation& repr) const return Tensor(); } -TransformSequence TransformSequence::inverse() const +TransformSequence TransformSequence::inverse() const { TransformSequence rt; for( auto i = m_transforms.rbegin(); i != m_transforms.rend(); ++i ) @@ -105,8 +105,12 @@ TransformSequence TransformSequence::inverse() const return rt; } -Tensor TransformSequence::operator()( const Transform::Representation& repr ) const +Tensor TransformSequence::operator()( const Transform::Representation& repr ) { + if( m_cache[repr].nElements() != 1 ) + { + return m_cache[repr]; + } if( m_transforms.size() == 0 ){ if( repr == Transform::Representation::Spinor ) return Identity(2); else return Identity(4); @@ -117,14 +121,15 @@ Tensor TransformSequence::operator()( const Transform::Representation& repr ) co for( size_t i = 1 ; i < m_transforms.size(); ++i ) { Tensor rti = m_transforms[i](repr); - rti.st(); + rti.st(true); rt = rti(a,b) * rt(b,c); } + m_cache[repr] = rt; return rt; } Tensor TransformSequence::operator()( const Tensor& tensor, - const Transform::Representation& repr ) const + const Transform::Representation& repr ) { Tensor::Index a,b,c; auto seq = this->operator()(repr); @@ -132,7 +137,7 @@ Tensor TransformSequence::operator()( const Tensor& tensor, } Tensor Transform::operator()( const Tensor& tensor, - const Transform::Representation& repr ) const + const Transform::Representation& repr ) const { Tensor::Index a,b; auto seq = this->operator()(repr); diff --git a/src/Wigner.cpp b/src/Wigner.cpp index 14ec302740c..952cf5ba6ef 100644 --- a/src/Wigner.cpp +++ b/src/Wigner.cpp @@ -121,32 +121,30 @@ TransformSequence AmpGen::wickTransform( const Tensor& P, return sequence; } -Expression AmpGen::wigner_D(const Tensor& P, - const double& J, - const double& lA, - const double& lB, - DebugSymbols* db, - const std::string& name ) +std::pair angCoordinates(const Tensor& P) { Expression pz = make_cse( P[2] / sqrt( P[0]*P[0] + P[1] * P[1] + P[2]*P[2] ) ); Expression pt2 = make_cse( P[0]*P[0] + P[1]*P[1] ); Expression px = P[0] / sqrt(pt2); Expression py = P[1] / sqrt(pt2); - - auto little_d = make_cse ( wigner_d( pz, J, lA, lB ) ); + return {pz, make_cse(px + 1i*py)}; +} +Expression AmpGen::wigner_D(const std::pair& P, + const double& J, + const double& lA, + const double& lB, + DebugSymbols* db) +{ + auto little_d = make_cse ( wigner_d( P.first, J, lA, lB ) ); if( J != 0 && db != nullptr ){ - db->emplace_back("pt2", pt2 ); - db->emplace_back("p2" , sqrt( P[0]*P[0] + P[1] * P[1] + P[2]*P[2] ) ); - db->emplace_back("ϕ("+name+")", atan2( py, px ) ); - db->emplace_back("θ("+name+")", acos(pz) ); db->emplace_back("d[" + std::to_string(J) +", " + std::to_string(lA) +", " + std::to_string(lB) +"](θ)", little_d ); db->emplace_back("D[" + std::to_string(J) +", " + std::to_string(lA) +", " + - std::to_string(lB) +"](Ω)", fpow(px+1i*py,lB-lA) * little_d ); + std::to_string(lB) +"](θ, Ω)", fpow(P.second,lB-lA) * little_d ); } - return fpow( px + 1i* py, lB - lA ) * little_d; + return fpow( P.second, lB - lA ) * little_d; } std::vector AmpGen::calculate_recoupling_constants( @@ -208,54 +206,54 @@ std::vector userHelicityCouplings( const std::string& key ){ return couplings; } - Expression AmpGen::helicityAmplitude(const Particle& particle, - const TransformSequence& parentFrame, + TransformSequence& parentFrame, const double& Mz, DebugSymbols* db, - int sgn ) + int sgn, + std::map* cachePtr ) { + if( cachePtr == nullptr ) cachePtr = new std::map(); if( particle.daughters().size() > 2 ) return 1; if( particle.daughters().size() == 1 ) - return helicityAmplitude( *particle.daughter(0), parentFrame, Mz, db, sgn ); + return helicityAmplitude( *particle.daughter(0), parentFrame, Mz, db, sgn, cachePtr); Tensor::Index a,b,c; auto myFrame = parentFrame; if( particle.spin() == 0 ) myFrame.clear(); Tensor pInParentFrame = parentFrame(particle.P()); pInParentFrame.st(); - auto my_sequence = wickTransform(pInParentFrame, fcn::sqrt(particle.massSq()), sgn, true ); + auto my_sequence = wickTransform(pInParentFrame, fcn::sqrt(particle.massSq()), sgn, true); + if( cachePtr->count(&particle) != 0 ) my_sequence = (*cachePtr)[&particle]; + else (*cachePtr)[&particle] = my_sequence; + if( ! particle.isHead() ) myFrame.add( my_sequence ); if( particle.isStable() ) { if( particle.props()->twoSpin() == 0 ) return Mz==0; // a scalar // polarisation spinor / vector etc. in the quantisation of the lab (i.e. along the z-axis or lab particle momentum) auto labPol = particle.externalSpinTensor(particle.polState(), db); - //ADD_DEBUG_TENSOR(labPol, db); auto inverseMyTransform = myFrame.inverse(); if( particle.props()->twoSpin() == 1 ) // so a fermion { if( NamedParameter("helicityAmplitude::NoSpinAlign", false ) ) return 2*Mz == particle.polState(); - auto basisSpinor_m1 = basisSpinor( 2*Mz, particle.props()->pdgID() ); - auto labSpinor_m1 = inverseMyTransform( basisSpinor_m1, Transform::Representation::Bispinor ); - //ADD_DEBUG_TENSOR(labSpinor_m1, db); + auto mzSpinor = basisSpinor( 2*Mz, particle.props()->pdgID() ); + auto mzSpinorInLab = inverseMyTransform( mzSpinor, Transform::Representation::Bispinor ); // lets just get the diagonal part // - ADD_DEBUG(Bar(labSpinor_m1)(a)*labPol(a), db ); - return make_cse( Bar(labSpinor_m1)(a)*labPol(a) ); + mzSpinorInLab.st(); + ADD_DEBUG(Bar(mzSpinorInLab)(a)*labPol(a), db ); + return make_cse( Bar(mzSpinorInLab)(a)*labPol(a) ); } if( particle.props()->twoSpin() == 2 ) // so a spin-one boson { auto frameVector = basisVector(Mz); auto labVector = inverseMyTransform( frameVector, Transform::Representation::Vector ); - auto rp = dot( labVector.conjugate(), labPol ); - //ADD_DEBUG_TENSOR(labVector, db); - ADD_DEBUG(rp, db ); - return rp; + return dot( labVector.conjugate(), labPol ); } } auto particle_couplings = particle.spinOrbitCouplings(false); auto L = particle.orbital(); - auto& d1 = *particle.daughter(0); - auto& d2 = *particle.daughter(1); + const auto& d1 = *particle.daughter(0); + const auto& d2 = *particle.daughter(1); double S = 999; if( particle.S() == 0 ){ auto it = std::find_if( particle_couplings.begin(), particle_couplings.end(), [&L](auto& l){ return l.first == L; } ); @@ -275,14 +273,15 @@ Expression AmpGen::helicityAmplitude(const Particle& particle, vectorToString( particle_couplings, ", ", []( auto& ls ){ return "("+std::to_string(int(ls.first)) + ", " + std::to_string(ls.second) +")";} ) ); } Expression total = 0; + std::pair hco = angCoordinates( myFrame(d1.P()) ); for( auto& coupling : recoupling_constants ) { auto dm = coupling.m1 - coupling.m2; if( (d1.name() == "gamma0" && coupling.m1 == 0) || (d2.name() == "gamma0" && coupling.m2 == 0) ) continue; - auto term = wigner_D(myFrame(d1.P()), particle.spin(), Mz, dm,db, d1.name()); - auto h1 = helicityAmplitude(d1, myFrame, coupling.m1, db, +1); - auto h2 = helicityAmplitude(d2, myFrame, coupling.m2, db, -1); + auto term = wigner_D(hco, particle.spin(), Mz, dm, db); + auto h1 = helicityAmplitude(d1, myFrame, coupling.m1, db, +1, cachePtr); + auto h2 = helicityAmplitude(d2, myFrame, coupling.m2, db, -1, cachePtr); if( db != nullptr ){ db->emplace_back( "coupling" , coupling.factor ); if( coupling.factor != 1 ) db->emplace_back( "C x DD'", coupling.factor * term * h1 * h2 ); From 78d0182499adc9792c6629cc63e11a31cd272eaf Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 9 Sep 2019 15:08:19 +0200 Subject: [PATCH 094/250] Add PolyNR for backgrounds --- AmpGen/Lineshapes.h | 5 +++++ src/ASTResolver.cpp | 1 - src/ErrorPropagator.cpp | 18 ++++++------------ src/Lineshapes/PolyNR.cpp | 40 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 src/Lineshapes/PolyNR.cpp diff --git a/AmpGen/Lineshapes.h b/AmpGen/Lineshapes.h index 4bd0989afe1..4ba61cc69fa 100644 --- a/AmpGen/Lineshapes.h +++ b/AmpGen/Lineshapes.h @@ -322,6 +322,11 @@ namespace AmpGen /** @ingroup Lineshapes class Poly * @brief Polynominal shape \f$ \mathcal{A}(s) = \sum^n_i c_i s^{i} \f$ where the sum is to lineshapeModifier::Degree, and the free parameters of the shape are lineshapeModifier_ci */ + DECLARE_LINESHAPE( PolyNR ); + + /** @ingroup Lineshapes class PolyNR + * @brief Polynominal shape \f$ \mathcal{A}(s) = \sqrt{ \sum_{ij} c_{ij} s^{i} (s^\prime)^{j} } \f$ where the sum is to lineshapeModifier::Degree, and the free parameters of the shape are lineshapeModifier_cij + */ DECLARE_LINESHAPE( Poly ); /** @ingroup Lineshapes class FOCUS diff --git a/src/ASTResolver.cpp b/src/ASTResolver.cpp index 8eec9f653ee..5d6c1a021ee 100644 --- a/src/ASTResolver.cpp +++ b/src/ASTResolver.cpp @@ -36,7 +36,6 @@ std::vector> ASTResolver::getOrderedSubExpression uint64_t key = t.first->key(); if( subTrees.count( key ) == 0 ) subTrees[ key ] = t.first->m_expression ; } - INFO("Reducing subtrees: " << m_tempTrees.size() << " " << subTrees.size() ); m_tempTrees.clear(); for( auto& st : subTrees ){ st.second.resolve( *this ); diff --git a/src/ErrorPropagator.cpp b/src/ErrorPropagator.cpp index 1d22a3fa192..44e1b72ae07 100644 --- a/src/ErrorPropagator.cpp +++ b/src/ErrorPropagator.cpp @@ -11,7 +11,6 @@ using namespace AmpGen; GaussErrorPropagator::GaussErrorPropagator( const TMatrixD& reducedCovariance, const std::vector& params, TRandom3* rnd ) : m_parameters( params ), m_rand( rnd ), m_decomposedCholesky( params.size(), params.size() ) { - for ( size_t x = 0; x < params.size(); ++x ) { auto p = params[x]; INFO( p->name() << " " << p->mean() << " +/- " << sqrt( reducedCovariance( x, x ) ) ); @@ -20,7 +19,12 @@ GaussErrorPropagator::GaussErrorPropagator( const TMatrixD& reducedCovariance, c TDecompChol decomposed( reducedCovariance ); decomposed.Decompose(); m_decomposedCholesky = decomposed.GetU(); - transpose(); + /// transpose the cholesky matrix + for ( int i = 0; i < m_decomposedCholesky.GetNrows(); ++i ) { + for ( int j = i + 1; j < m_decomposedCholesky.GetNrows(); ++j ){ + std::swap( m_decomposedCholesky(i, j), m_decomposedCholesky(j, i) ); + } + } } void GaussErrorPropagator::perturb() @@ -40,16 +44,6 @@ void GaussErrorPropagator::reset() for ( unsigned int j = 0; j < m_parameters.size(); ++j ) m_parameters[j]->setCurrentFitVal( m_startingValues[j] ); } -void GaussErrorPropagator::transpose() -{ - for ( int i = 0; i < m_decomposedCholesky.GetNrows(); ++i ) { - for ( int j = i + 1; j < m_decomposedCholesky.GetNrows(); ++j ) { - double tmp = m_decomposedCholesky( j, i ); - m_decomposedCholesky( j, i ) = m_decomposedCholesky( i, j ); - m_decomposedCholesky( i, j ) = tmp; - } - } -} LinearErrorPropagator::LinearErrorPropagator( const TMatrixD& reducedCovarianceMatrix, const std::vector& params ) : m_cov( reducedCovarianceMatrix ), m_parameters( params ) diff --git a/src/Lineshapes/PolyNR.cpp b/src/Lineshapes/PolyNR.cpp new file mode 100644 index 00000000000..7f1c0a49a91 --- /dev/null +++ b/src/Lineshapes/PolyNR.cpp @@ -0,0 +1,40 @@ +#include + +#include "AmpGen/Expression.h" +#include "AmpGen/Factory.h" +#include "AmpGen/Lineshapes.h" +#include "AmpGen/NamedParameter.h" + +using namespace AmpGen; + +DEFINE_GENERIC_SHAPE( PolyNR ) +{ + auto p0 = *p.daughter(0); + auto p1 = *p.daughter(1); + auto p2 = *p.daughter(2); + auto p01 = (p0.P() + p1.P()); + auto p02 = (p0.P() + p2.P()); + auto s01 = dot( p01, p01 ); + auto s02 = dot( p02, p02 ); + size_t degree = NamedParameter( lineshapeModifier + "::Degree" ) +1; + std::vector< std::vector > C( degree, std::vector(degree) ); + + for( size_t i = 0 ; i != degree ; ++i ) + { + for( size_t j = 0 ; j != degree ; ++j ){ + auto pname = lineshapeModifier +"_"+std::to_string(i) + "_"+std::to_string(j) ; + C[i][j] = Parameter(pname, 0); + if( dbexpressions != nullptr ) + dbexpressions->emplace_back( pname, C[i][j] ); + } + } + Expression rt; + for( size_t i = 0 ; i != degree; ++i ) + { + for( size_t j = 0 ; j != degree ; ++j ) + { + rt = rt + C[i][j] * fcn::pow(s01, i) * fcn::pow(s02, j); + } + } + return rt; +} From 1c7f4d682cb53bd0069c276bc7b4182f4efb35f8 Mon Sep 17 00:00:00 2001 From: mstahl Date: Thu, 22 Aug 2019 10:16:31 -0400 Subject: [PATCH 095/250] changing names in output tree --- src/EventType.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/EventType.cpp b/src/EventType.cpp index b63e839dcd0..3b449419b63 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -25,7 +25,7 @@ using namespace AmpGen; std::string convertTeXtoROOT(std::string input); EventType::EventType( const std::vector& particleNames, const bool& isTD ) : m_timeDependent( isTD ) -{ +{ if ( particleNames.size() < 3 ) { // Mother plus two daughters minimum required ERROR( "Not enough particles in event type: " << particleNames[0] << " size = " << particleNames.size() ); throw std::runtime_error( "Not enough particles listed in particle names! Was it defined?" ); @@ -47,7 +47,7 @@ EventType::EventType( const std::vector& particleNames, const bool& ERROR( "Particle not found: " << particle ); return; } - m_particleNamesPickled.push_back( replaceAll( replaceAll( particle, "+", "~" ), "-", "#" ) ); + m_particleNamesPickled.push_back( replaceAll( replaceAll( particle, "+", "p" ), "-", "m" ) ); } DEBUG( m_mother << " = " << m_motherMass << " -> " ); for ( unsigned int i = 0; i < m_particleNames.size(); ++i ) { @@ -65,10 +65,12 @@ std::map EventType::getEventFormat( const bool& outputNames { std::map returnValue; bool include_energy = NamedParameter("EventType::IncludeEnergy", true ); - size_t s = include_energy ? 4 : 3; + size_t s = include_energy ? 4 : 3; for ( unsigned int ip = 0; ip < size(); ++ip ) { + const auto parsed_name = std::count(m_particleNamesPickled.begin(),m_particleNamesPickled.end(),m_particleNamesPickled[ip]) == 1 ? + m_particleNamesPickled[ip] : m_particleNamesPickled[ip] + std::to_string( ip + 1 ); std::string stub = - outputNames ? "_" + std::to_string( ip + 1 ) + "_" + m_particleNamesPickled[ip] : std::to_string( ip ); + outputNames ? parsed_name : std::to_string( ip ); if( include_energy ) returnValue[stub + "_E"] = s * ip + 3; returnValue[stub + "_Px"] = s * ip + 0; returnValue[stub + "_Py"] = s * ip + 1; @@ -78,7 +80,7 @@ std::map EventType::getEventFormat( const bool& outputNames for( auto& extend : m_eventTypeExtensions ) returnValue[extend] = returnValue.size(); return returnValue; } -void EventType::extendEventType( const std::string& branch ) +void EventType::extendEventType( const std::string& branch ) { m_eventTypeExtensions.push_back(branch); } @@ -93,14 +95,14 @@ std::pair EventType::minmax( const std::vector& indices, if ( std::find( indices.begin(), indices.end(), x ) == indices.end() ) max -= mass( x ); return std::pair( min * min / GeV, max * max / GeV ); } -std::pair EventType::count(const size_t& index) const +std::pair EventType::count(const size_t& index) const { if( index >= size() ){ ERROR("Looking for matching particles to index = " << index << " > size of eventType"); return std::pair(0, 0); } std::pair rt(0,0); - for( size_t j = 0 ; j < size(); ++j ){ + for( size_t j = 0 ; j < size(); ++j ){ if( EventType::operator[](j) == EventType::operator[](index) ){ rt.second++; if( j < index ) rt.first++; @@ -137,7 +139,7 @@ EventType EventType::conj( const bool& headOnly, const bool& dontConjHead ) cons { std::vector type; type.push_back( dontConjHead ? m_mother : ParticlePropertiesList::get( m_mother )->anti().name() ); - std::transform( m_particleNames.begin(), m_particleNames.end(), std::back_inserter(type), + std::transform( m_particleNames.begin(), m_particleNames.end(), std::back_inserter(type), [&](auto& x){ return headOnly ? x : ParticlePropertiesList::get(x)->anti().name() ; } ); return EventType( type ); } @@ -148,13 +150,13 @@ std::vector EventType::defaultProjections(const size_t& nBins) const std::vector projections; for ( size_t r = 2; r < size(); ++r ) { /// loop over sizes /// std::vector> combR = nCr( size(), r ); - std::transform( combR.begin(), combR.end(), std::back_inserter(projections), + std::transform( combR.begin(), combR.end(), std::back_inserter(projections), [&](auto& index){ return this->projection(nBins, index, defaultObservable ); } ); } return projections; } -Projection EventType::projection(const size_t& nBins, const std::vector& indices, const std::string& observable) const +Projection EventType::projection(const size_t& nBins, const std::vector& indices, const std::string& observable) const { bool useRootLabelling = NamedParameter("EventType::UseRootTEX", false ); auto mm = minmax(indices, true); From a255de11244f0d94d544d2fbd63a01803cf81482 Mon Sep 17 00:00:00 2001 From: mstahl Date: Wed, 11 Sep 2019 10:20:57 -0400 Subject: [PATCH 096/250] added option to choose different naming in output tree --- AmpGen/EventType.h | 29 +++++++++++++++-------------- src/EventType.cpp | 26 +++++++++++++++++++------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/AmpGen/EventType.h b/AmpGen/EventType.h index d7b8fd04606..fe9f41e445f 100644 --- a/AmpGen/EventType.h +++ b/AmpGen/EventType.h @@ -9,8 +9,8 @@ namespace AmpGen { - class Projection; - class Event; + class Projection; + class Event; /**@class EventType Deals with final state configuration of events, specifically dealing with the ordering of particles in trees. @@ -22,19 +22,19 @@ namespace AmpGen /// Default constructor EventType() = default; - /// Takes a list of particles, beginning with the head of the decay and - /// then then final state particles, and a flag as to whether to include time dependence. + /// Takes a list of particles, beginning with the head of the decay and + /// then then final state particles, and a flag as to whether to include time dependence. EventType( const std::vector&, const bool& isTD = false ); - + /// Returns the CP-conjugated event type. Can also require that only the initial/ - /// final state is conjugated. By default, conjugates both. + /// final state is conjugated. By default, conjugates both. EventType conj( const bool& headOnly = 0, const bool& dontConjHead = 0 ) const; - - /// Returns the event format, that matches between expressions and the names used in Particle. + + /// Returns the event format, that matches between expressions and the names used in Particle. std::map getEventFormat( const bool& outputNames = false ) const; - /// Counts the number of particles in this event type with - /// the same name as the index'th name. + /// Counts the number of particles in this event type with + /// the same name as the index'th name. std::pair count(const size_t& index) const; std::pair minmax( const std::vector& indices, bool isGeV = false ) const; std::vector masses() const; @@ -47,7 +47,7 @@ namespace AmpGen size_t size() const; size_t dof() const; std::string operator[]( const size_t& index ) const; - std::string decayDescriptor() const; + std::string decayDescriptor() const; std::string label( const size_t& index, bool isRoot = true ) const; std::string label( const std::vector& index, bool isRoot = true ) const; std::vector defaultProjections(const size_t& nBins) const; @@ -58,10 +58,10 @@ namespace AmpGen void extendEventType( const std::string& branch ); - /// Functor to randomly symmetrise data of this event type, using the Fisher-Yates shuffle. + /// Functor to randomly symmetrise data of this event type, using the Fisher-Yates shuffle. std::function symmetriser() const; - /// Calculates the number of spin indices associated with the initial and final state, i.e. the rank of the relevant transition matrix. + /// Calculates the number of spin indices associated with the initial and final state, i.e. the rank of the relevant transition matrix. std::pair dim() const; private: @@ -72,7 +72,8 @@ namespace AmpGen std::vector m_particleMasses; ///< masses of decay products bool m_timeDependent; ///< Flag to include a decay time as the last element in the event vector std::vector m_eventTypeExtensions; ///< extended event data - std::pair m_dim; ///< Rank of the relevant transition matrix + std::pair m_dim; ///< Rank of the relevant transition matrix + bool m_alt_part_names; ///< alternative naming in ouput tree (e.g. Xi- pi+ pi+ becomes Xim pip0 pip1 rather than _1_Xi# _2_pi~ _3_pi~) }; std::ostream& operator<<( std::ostream& os, const EventType& type ); } // namespace AmpGen diff --git a/src/EventType.cpp b/src/EventType.cpp index 3b449419b63..90730cc1785 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -39,6 +39,7 @@ EventType::EventType( const std::vector& particleNames, const bool& ERROR( "Particle not found: " << m_mother ); return; } + m_alt_part_names = NamedParameter("EventType::AlternativeParicleNames", false ); for ( auto& particle : m_particleNames ) { auto prop = ParticlePropertiesList::get( particle ); if ( prop != nullptr ) @@ -47,7 +48,10 @@ EventType::EventType( const std::vector& particleNames, const bool& ERROR( "Particle not found: " << particle ); return; } - m_particleNamesPickled.push_back( replaceAll( replaceAll( particle, "+", "p" ), "-", "m" ) ); + if(m_alt_part_names) + m_particleNamesPickled.push_back( replaceAll( replaceAll( particle, "+", "p" ), "-", "m" ) ); + else + m_particleNamesPickled.push_back( replaceAll( replaceAll( particle, "+", "~" ), "-", "#" ) ); } DEBUG( m_mother << " = " << m_motherMass << " -> " ); for ( unsigned int i = 0; i < m_particleNames.size(); ++i ) { @@ -67,10 +71,18 @@ std::map EventType::getEventFormat( const bool& outputNames bool include_energy = NamedParameter("EventType::IncludeEnergy", true ); size_t s = include_energy ? 4 : 3; for ( unsigned int ip = 0; ip < size(); ++ip ) { - const auto parsed_name = std::count(m_particleNamesPickled.begin(),m_particleNamesPickled.end(),m_particleNamesPickled[ip]) == 1 ? - m_particleNamesPickled[ip] : m_particleNamesPickled[ip] + std::to_string( ip + 1 ); - std::string stub = - outputNames ? parsed_name : std::to_string( ip ); + std::string parsed_name; + if(m_alt_part_names) + //check if there are multiple identical particles + if(std::count(m_particleNamesPickled.begin(),m_particleNamesPickled.end(),m_particleNamesPickled[ip]) > 1) + //if yes, append an index + parsed_name = m_particleNamesPickled[ip] + + std::to_string(std::count(m_particleNamesPickled.begin(),m_particleNamesPickled.begin()+ip, m_particleNamesPickled[ip])); + else // just take the already chosen name + parsed_name = m_particleNamesPickled[ip]; + else + parsed_name = "_" + std::to_string( ip + 1 ) + "_" + m_particleNamesPickled[ip]; + std::string stub = outputNames ? parsed_name : std::to_string( ip ); if( include_energy ) returnValue[stub + "_E"] = s * ip + 3; returnValue[stub + "_Px"] = s * ip + 0; returnValue[stub + "_Py"] = s * ip + 1; @@ -196,12 +208,12 @@ size_t EventType::dof() const { return 3 * size() - 7; } std::function EventType::symmetriser() const { std::map> particleOrdering; - for ( size_t i = 0; i < m_particleNames.size(); ++i ) + for ( size_t i = 0; i < m_particleNames.size(); ++i ) particleOrdering[m_particleNames[i]].push_back( i ); std::vector> shuffles; for ( auto& im : particleOrdering ) if ( im.second.size() != 1 ) shuffles.push_back( im.second ); - + int seed = NamedParameter( "EventType::SymmetriserSeed", 12 ); std::mt19937 rng( seed ); for ( auto& shuffle : shuffles ) { From 16d81fc0b9bea98b8ad6f109a762f6a79ab3b198 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 12 Sep 2019 14:29:32 +0200 Subject: [PATCH 097/250] Minor fixes to enum, allow direct use with NamedParameters, switched to using these in AmplitudeRules --- AmpGen/Minimiser.h | 8 +++----- AmpGen/NamedParameter.h | 7 ++----- AmpGen/enum.h | 40 +++++++++++++++++++++++++++----------- apps/Generator.cpp | 21 ++++++++++---------- src/AmplitudeRules.cpp | 19 ++++++++++-------- src/CompilerWrapper.cpp | 1 + src/FitResult.cpp | 2 +- src/Generator.cpp | 1 + src/MinuitParameter.cpp | 3 +++ src/MinuitParameterSet.cpp | 10 +++++----- 10 files changed, 67 insertions(+), 45 deletions(-) diff --git a/AmpGen/Minimiser.h b/AmpGen/Minimiser.h index b66de44df39..cbe04fe6b13 100644 --- a/AmpGen/Minimiser.h +++ b/AmpGen/Minimiser.h @@ -32,7 +32,7 @@ namespace AmpGen { private: template - struct Has + struct HasGetVal { typedef char YesType[1]; typedef char NoType[2]; @@ -41,14 +41,12 @@ namespace AmpGen enum { value = sizeof(test(0)) == sizeof(YesType) }; }; - - public: - template typename std::enable_if_t::value, void> setFunction( TYPE& fcn ) + template typename std::enable_if_t::value, void> setFunction( TYPE& fcn ) { m_theFunction = [&fcn]() { return fcn.getVal(); }; } - template typename std::enable_if_t::value, void> setFunction(TYPE& fcn) + template typename std::enable_if_t::value, void> setFunction(TYPE& fcn) { m_theFunction = [&fcn](){ return fcn() ; } ; } diff --git a/AmpGen/NamedParameter.h b/AmpGen/NamedParameter.h index f0598abab89..bbaa6056b12 100644 --- a/AmpGen/NamedParameter.h +++ b/AmpGen/NamedParameter.h @@ -147,24 +147,21 @@ namespace AmpGen return return_container; } }; - template - std::ostream& operator<<( std::ostream& os, const NamedParameter& np ); + template std::ostream& operator<<( std::ostream& os, const NamedParameter& np ); std::string optionalHelpString(const std::string& header, const std::vector>& args); } - template std::ostream& AmpGen::operator<<( std::ostream& os, const AmpGen::NamedParameter& np ) { os << np.name() ; for ( size_t i = 0; i < np.size(); i++ ) { if( i == 0 ) os << " = "; - os << np.getVal( i ); + os << np.getVal(i); if ( i != np.size() ) os << " "; } return os; } #endif -// diff --git a/AmpGen/enum.h b/AmpGen/enum.h index 58eefc2d7e4..625127ea146 100644 --- a/AmpGen/enum.h +++ b/AmpGen/enum.h @@ -1,20 +1,37 @@ +#ifndef AMPGEN_ENUM_H +#define AMPGEN_ENUM_H 1 #include "AmpGen/MsgService.h" -#define declare_enum(name, ...) enum name {__VA_ARGS__}; \ -template T parse(const std::string& word){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::parse(word, args); } \ -template std::string to_string( const T& enumItem ){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::to_string(enumItem, args) ; } +#define declare_enum(name, ...) \ +enum class name {__VA_ARGS__}; \ +template <> name AmpGen::parse(const std::string& word); \ +template <> std::string AmpGen::to_string( const name& enumItem ); \ +std::ostream& operator<<( std::ostream& os, const name& np); + +#define complete_enum(name, ...) \ +template <> name AmpGen::parse(const std::string& word){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::parse(word, args); } \ +template <> std::string AmpGen::to_string( const name& enumItem ){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::to_string(enumItem, args) ; } \ +template <> name AmpGen::lexical_cast(const std::string& word, bool& /*status*/){ return parse(word); } \ +std::ostream& operator<<(std::ostream& os, const name& np){ return os << to_string(np);} + +#define make_enum(name, ...) \ +declare_enum(name, __VA_ARGS__) \ +complete_enum(name, __VA_ARGS__) \ namespace AmpGen { + template T parse( const std::string& word ){ return T(); } + template std::string to_string( const T& enumItem ){ return ""; } + namespace detail { template T parse(const std::string& word, const char* args) { char* p; auto number = strtoul( word.c_str(), &p, 10 ); if( *p == 0 ) return T(number); - size_t counter = 0; - size_t begin = 0; - size_t end = 0; - auto compare = [](const char* word, const char* otherWord, const size_t& nChar) + unsigned counter = 0; + unsigned begin = 0; + unsigned end = 0; + auto compare = [](const char* word, const char* otherWord, const unsigned& nChar) { for( size_t x = 0; x != nChar ; ++x) if( word[x] != otherWord[x] ) return false; return true; @@ -32,10 +49,10 @@ namespace AmpGen { } template std::string to_string(const T& enumItem, const char* args) { - size_t counter = 0; - size_t sBegin = 0; - size_t sLength = 0; - for( ; args[sBegin] != '\0' && counter != enumItem; sBegin++ ) + unsigned counter = 0; + unsigned sBegin = 0; + unsigned sLength = 0; + for( ; args[sBegin] != '\0' && counter != unsigned(enumItem); sBegin++ ) { if( args[sBegin] == ',' ) counter++; } @@ -45,3 +62,4 @@ namespace AmpGen { } } } +#endif diff --git a/apps/Generator.cpp b/apps/Generator.cpp index 543bb5fe4aa..b855bedb3d9 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -26,9 +26,12 @@ #include "AmpGen/NamedParameter.h" #include "AmpGen/PolarisedSum.h" #include "AmpGen/OptionsParser.h" +#include "AmpGen/enum.h" using namespace AmpGen; +make_enum(generatorType, CoherentSum, PolarisedSum, FixedLib, RGenerator) + struct FixedLibPDF { void* lib; AmpGen::DynamicFCN PDF; @@ -60,6 +63,7 @@ template signalGenerator.fillEventList( pdf, events, nEvents ); } + int main( int argc, char** argv ) { OptionsParser::setArgs( argc, argv ); @@ -67,9 +71,8 @@ int main( int argc, char** argv ) size_t nEvents = NamedParameter ("nEvents" , 1, "Total number of events to generate" ); size_t blockSize = NamedParameter ("BlockSize", 100000, "Number of events to generate per block" ); int seed = NamedParameter ("Seed" , 0, "Random seed used in event Generation" ); - std::string outfile = NamedParameter("Output" , "Generate_Output.root" , "Name of output file" ); - - std::string gen_type = NamedParameter( "Type", "CoherentSum", optionalHelpString("Generator configuration to use:", + std::string outfile = NamedParameter("Output" , "Generate_Output.root" , "Name of output file" ); + auto genType = NamedParameter( "Type", generatorType::CoherentSum, optionalHelpString("Generator configuration to use:", { {"CoherentSum", "Full phase-space generator with (pseudo)scalar amplitude"} , {"PolarisedSum", "Full phase-space generator with particles carrying spin in the initial/final states"} , {"FixedLib", "Full phase-space generator with an amplitude from a precompiled library"} @@ -92,8 +95,6 @@ int main( int argc, char** argv ) MinuitParameterSet MPS; MPS.loadFromStream(); - Particle p; - EventType eventType( NamedParameter( "EventType" , "", "EventType to generate, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(), NamedParameter( "GenerateTimeDependent", false , "Flag to include possible time dependence of the amplitude") ); @@ -102,23 +103,23 @@ int main( int argc, char** argv ) INFO("Generating events with type = " << eventType ); - if ( gen_type == "CoherentSum" ) { + if ( genType == generatorType::CoherentSum ) { CoherentSum sig( eventType, MPS ); PhaseSpace phsp(eventType,&rand); GenerateEvents( accepted, sig, phsp , nEvents, blockSize, &rand ); } - else if ( gen_type == "PolarisedSum" ){ + else if ( genType == generatorType::PolarisedSum ){ PolarisedSum sig( eventType, MPS ); RecursivePhaseSpace phsp( sig.matrixElements()[0].decayTree.quasiStableTree() , eventType, &rand ); GenerateEvents( accepted, sig, phsp, nEvents, blockSize, &rand ); } - else if ( gen_type == "RGenerator" ) { + else if ( genType == generatorType::RGenerator ) { CoherentSum sig( eventType, MPS, "" ); Generator signalGenerator( sig[0].decayTree.quasiStableTree(), eventType ); signalGenerator.setRandom( &rand ); signalGenerator.fillEventList( sig, accepted, nEvents ); } - else if ( gen_type == "FixedLib" ) { + else if ( genType == generatorType::FixedLib ) { Generator<> signalGenerator( eventType ); signalGenerator.setRandom( &rand ); signalGenerator.setBlockSize( blockSize ); @@ -127,7 +128,7 @@ int main( int argc, char** argv ) signalGenerator.fillEventList( pdf, accepted, nEvents ); } else { - ERROR("Did not recognise configuration: " << gen_type ); + FATAL("Did not recognise configuration: " << genType ); } if( accepted.size() == 0 ) return -1; TFile* f = TFile::Open( outfile.c_str(), "RECREATE" ); diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index 89d0ed39b5d..e0956f042b2 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -87,19 +87,22 @@ EventType AmplitudeRule::eventType() const return EventType( particleNames ); } +declare_enum(coordinateType, cartesian, polar) +declare_enum(angType, deg, rad) +complete_enum(coordinateType, cartesian, polar) +complete_enum(angType, deg, rad) + CouplingConstant::CouplingConstant(const AmplitudeRule& pA) { couplings.emplace_back(pA.m_re,pA.m_im); - std::string cartOrPolar = NamedParameter("CouplingConstant::Coordinates" ,"cartesian"); - std::string degOrRad = NamedParameter("CouplingConstant::AngularUnits","rad"); - if( cartOrPolar == "polar" ){ - isCartesian = false; - } - else if ( cartOrPolar != "cartesian" ){ + coordinateType coord = NamedParameter("CouplingConstant::Coordinates", coordinateType::cartesian); + angType degOrRad = NamedParameter("CouplingConstant::AngularUnits", angType::rad); + if( coord == coordinateType::polar ) isCartesian = false; + else if ( coord != coordinateType::cartesian){ FATAL("Coordinates for coupling constants must be either cartesian or polar"); } - if ( degOrRad == "deg") sf = M_PI / 180; - else if ( degOrRad != "rad"){ + if ( degOrRad == angType::deg) sf = M_PI / 180; + else if ( degOrRad != angType::rad){ FATAL("CouplingConstant::AngularUnits must be either rad or deg"); } } diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index 4401b198b4d..6a3b63abbb5 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -54,6 +54,7 @@ std::string CompilerWrapper::generateFilename() if ( status == -1 ) { ERROR( "Failed to generate temporary filename " << status ); } + std::remove( buffer ); return buffer; } diff --git a/src/FitResult.cpp b/src/FitResult.cpp index 5126199f05c..7142fadc55b 100644 --- a/src/FitResult.cpp +++ b/src/FitResult.cpp @@ -133,7 +133,7 @@ void FitResult::writeToFile( const std::string& fname ) for (size_t i = 0; i < (size_t)m_covarianceMatrix.GetNrows(); ++i ) { auto param = m_mps->at(i); outlog << "Parameter" - << " " << param->name() << " " << param->flag() << " " << param->mean() << " " + << " " << param->name() << " " << to_string(param->flag()) << " " << param->mean() << " " << ( param->isFree() ? m_mps->at(i)->err() : 0 ) << " "; for (size_t j = 0; j < (size_t)m_covarianceMatrix.GetNcols(); ++j ) outlog << m_covarianceMatrix[i][j] << " "; outlog << std::endl; diff --git a/src/Generator.cpp b/src/Generator.cpp index a18115b9b1b..8383d4d5cac 100644 --- a/src/Generator.cpp +++ b/src/Generator.cpp @@ -14,3 +14,4 @@ extern "C" void AmpGen::PyGenerate(const char* eventType, double* out, const uns out[events[i].size() * i + j] = events[i][j]; } } + diff --git a/src/MinuitParameter.cpp b/src/MinuitParameter.cpp index f61202f17f5..b4019e52063 100644 --- a/src/MinuitParameter.cpp +++ b/src/MinuitParameter.cpp @@ -1,6 +1,7 @@ // author: Jonas Rademacker (Jonas.Rademacker@bristol.ac.uk) // status: Mon 9 Feb 2009 19:17:55 GMT #include "AmpGen/MinuitParameter.h" +#include "AmpGen/Utilities.h" #include @@ -8,6 +9,8 @@ using namespace AmpGen; +complete_enum( Flag, Free, Hide, Fix, CompileTimeConstant ) + MinuitParameter::MinuitParameter( const std::string& name, const Flag& fix, const double& mean, const double& step, const double& mi, const double& ma ) : m_flag( fix ), m_name( name ), m_meanInit( mean ), m_stepInit( step ), m_minInit( mi ), m_maxInit( ma ) diff --git a/src/MinuitParameterSet.cpp b/src/MinuitParameterSet.cpp index 367185d5917..4e3cc63f140 100644 --- a/src/MinuitParameterSet.cpp +++ b/src/MinuitParameterSet.cpp @@ -136,7 +136,7 @@ void MinuitParameterSet::tryParameter( const std::vector& line ) if( !status ) return; auto flag = parse( line[1] ); if ( OptionsParser::printHelp() ) - INFO( "MINUIT: Registered " << line[0] << " (flag " << flag << ") = " << mean << ", step=" << step << " ("<< min << "," << max << ")" ); + INFO( "MINUIT: Registered " << line[0] << " ( " << to_string(flag) << ") = " << mean << ", step=" << step << " ("<< min << "," << max << ")" ); add( new MinuitParameter( line[0], flag, mean, step, min, max ) ); } if ( line.size() == 7 || line.size() == 11 ) { @@ -151,11 +151,11 @@ void MinuitParameterSet::tryParameter( const std::vector& line ) double max_im = hasLimits ? lexical_cast( line[10], status ) : 0; if ( !status ) return; - auto flag_re = parse(line[1]); - auto flag_im = parse(line[4 + 2*hasLimits]); + auto flag_re = parse(line[1]); + auto flag_im = parse(line[4 + 2*hasLimits]); if ( OptionsParser::printHelp() ) { - INFO( "MINUIT: Complex " << line[0] << "_Re (flag " << flag_re << ") = " << mean_re << ", step=" << step_re << " (" << min_re << "," << max_re << ")" ); - INFO( "MINUIT: Complex " << line[0] << "_Im (flag " << flag_im << ") = " << mean_im << ", step=" << step_im << " (" << min_im << "," << max_im << ")" ); + INFO( "MINUIT: Complex " << line[0] << "_Re ( " << to_string(flag_re) << ") = " << mean_re << ", step=" << step_re << " (" << min_re << "," << max_re << ")" ); + INFO( "MINUIT: Complex " << line[0] << "_Im ( " << to_string(flag_im) << ") = " << mean_im << ", step=" << step_im << " (" << min_im << "," << max_im << ")" ); } add( new MinuitParameter( line[0] + "_Re", flag_re, mean_re, step_re, min_re, max_re ) ); add( new MinuitParameter( line[0] + "_Im", flag_im, mean_im, step_im, min_im, max_im ) ); From dab084ce6761bc4d094e088eb4089eaf120202e3 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 12 Sep 2019 14:55:24 +0200 Subject: [PATCH 098/250] fix clang warnings --- AmpGen/Minimiser.h | 1 - AmpGen/enum.h | 21 ++++++++++++--------- apps/Generator.cpp | 2 +- src/AmplitudeRules.cpp | 9 +++++---- src/MinuitParameter.cpp | 4 +++- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/AmpGen/Minimiser.h b/AmpGen/Minimiser.h index cbe04fe6b13..66a6580f682 100644 --- a/AmpGen/Minimiser.h +++ b/AmpGen/Minimiser.h @@ -89,7 +89,6 @@ namespace AmpGen std::vector m_mapping = {}; int m_status = {0}; unsigned int m_nParams = {0}; - unsigned int m_lastPrint = {0}; unsigned int m_printLevel = {0}; double m_ll_zero = {0}; bool m_normalise = {false}; diff --git a/AmpGen/enum.h b/AmpGen/enum.h index 625127ea146..3e296c8be8d 100644 --- a/AmpGen/enum.h +++ b/AmpGen/enum.h @@ -4,19 +4,22 @@ #define declare_enum(name, ...) \ enum class name {__VA_ARGS__}; \ -template <> name AmpGen::parse(const std::string& word); \ -template <> std::string AmpGen::to_string( const name& enumItem ); \ +template <> name parse(const std::string& word); \ +template <> std::string to_string( const name& enumItem ); \ std::ostream& operator<<( std::ostream& os, const name& np); #define complete_enum(name, ...) \ -template <> name AmpGen::parse(const std::string& word){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::parse(word, args); } \ -template <> std::string AmpGen::to_string( const name& enumItem ){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::to_string(enumItem, args) ; } \ -template <> name AmpGen::lexical_cast(const std::string& word, bool& /*status*/){ return parse(word); } \ -std::ostream& operator<<(std::ostream& os, const name& np){ return os << to_string(np);} +template <> name parse(const std::string& word){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::parse(word, args); } \ +template <> std::string to_string( const name& enumItem ){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::to_string(enumItem, args) ; } \ +template <> name lexical_cast(const std::string& word, bool& /*status*/){ return parse(word); } \ +std::ostream& AmpGen::operator<<(std::ostream& os, const name& np){ return os << to_string(np);} -#define make_enum(name, ...) \ -declare_enum(name, __VA_ARGS__) \ -complete_enum(name, __VA_ARGS__) \ +#define make_enum(name, ...) \ +enum class name {__VA_ARGS__}; \ +template <> name parse(const std::string& word){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::parse(word, args); } \ +template <> std::string to_string( const name& enumItem ){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::to_string(enumItem, args) ; } \ +template <> name lexical_cast(const std::string& word, bool& /*status*/){ return parse(word); } \ +std::ostream& operator<<(std::ostream& os, const name& np){ return os << to_string(np);} namespace AmpGen { template T parse( const std::string& word ){ return T(); } diff --git a/apps/Generator.cpp b/apps/Generator.cpp index b855bedb3d9..26751a0da1d 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -30,7 +30,7 @@ using namespace AmpGen; -make_enum(generatorType, CoherentSum, PolarisedSum, FixedLib, RGenerator) +namespace AmpGen { make_enum(generatorType, CoherentSum, PolarisedSum, FixedLib, RGenerator) } struct FixedLibPDF { void* lib; diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index e0956f042b2..ad6def17097 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -87,10 +87,11 @@ EventType AmplitudeRule::eventType() const return EventType( particleNames ); } -declare_enum(coordinateType, cartesian, polar) -declare_enum(angType, deg, rad) -complete_enum(coordinateType, cartesian, polar) -complete_enum(angType, deg, rad) +namespace AmpGen +{ + make_enum(coordinateType, cartesian, polar) + make_enum(angType, deg, rad) +} CouplingConstant::CouplingConstant(const AmplitudeRule& pA) { diff --git a/src/MinuitParameter.cpp b/src/MinuitParameter.cpp index b4019e52063..26ae2e5f1ba 100644 --- a/src/MinuitParameter.cpp +++ b/src/MinuitParameter.cpp @@ -9,7 +9,9 @@ using namespace AmpGen; -complete_enum( Flag, Free, Hide, Fix, CompileTimeConstant ) +namespace AmpGen { + complete_enum( Flag, Free, Hide, Fix, CompileTimeConstant ) +} MinuitParameter::MinuitParameter( const std::string& name, const Flag& fix, const double& mean, const double& step, const double& mi, const double& ma ) From 44ca30264d2b3431aaa934b67e8362378340d2bc Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 12 Sep 2019 15:10:17 +0200 Subject: [PATCH 099/250] once more for luck --- AmpGen/enum.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AmpGen/enum.h b/AmpGen/enum.h index 3e296c8be8d..22abf25ba28 100644 --- a/AmpGen/enum.h +++ b/AmpGen/enum.h @@ -12,7 +12,7 @@ std::ostream& operator<<( std::ostream& os, const name& np); template <> name parse(const std::string& word){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::parse(word, args); } \ template <> std::string to_string( const name& enumItem ){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::to_string(enumItem, args) ; } \ template <> name lexical_cast(const std::string& word, bool& /*status*/){ return parse(word); } \ -std::ostream& AmpGen::operator<<(std::ostream& os, const name& np){ return os << to_string(np);} +std::ostream& operator<<(std::ostream& os, const name& np){ return os << to_string(np);} #define make_enum(name, ...) \ enum class name {__VA_ARGS__}; \ From f9d1a7f8ad8b606d122cab17da81a229a8081df2 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 12 Sep 2019 15:47:45 +0200 Subject: [PATCH 100/250] Fixes to the stricter type checking of enums --- AmpGen/MinuitParameterSet.h | 4 ++-- src/MinuitParameterSet.cpp | 4 ++-- src/PolarisedSum.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/AmpGen/MinuitParameterSet.h b/AmpGen/MinuitParameterSet.h index 223269cdc27..e72c92ce63d 100644 --- a/AmpGen/MinuitParameterSet.h +++ b/AmpGen/MinuitParameterSet.h @@ -28,9 +28,9 @@ namespace AmpGen MinuitParameterSet getFloating(); bool add( MinuitParameter* parPtr ); - MinuitParameter* add(const std::string& name, const unsigned int& flag, const double& mean, const double& sigma, const double& min = 0, const double& max = 0 ); + MinuitParameter* add(const std::string& name, const Flag& flag, const double& mean, const double& sigma, const double& min = 0, const double& max = 0 ); bool unregister( MinuitParameter* patPtr ); - MinuitParameter* addOrGet(const std::string& name, const unsigned int& flag, const double& mean, + MinuitParameter* addOrGet(const std::string& name, const Flag& flag, const double& mean, const double& sigma, const double& min = 0, const double& max = 0 ); void loadFromStream(); void loadFromFile( const std::string& name ); diff --git a/src/MinuitParameterSet.cpp b/src/MinuitParameterSet.cpp index 4e3cc63f140..5040f6ede6e 100644 --- a/src/MinuitParameterSet.cpp +++ b/src/MinuitParameterSet.cpp @@ -51,7 +51,7 @@ bool MinuitParameterSet::addToEnd( MinuitParameter* parPtr ) return success; } -MinuitParameter* MinuitParameterSet::add( const std::string& name, const unsigned int& flag, const double& mean, +MinuitParameter* MinuitParameterSet::add( const std::string& name, const Flag& flag, const double& mean, const double& sigma, const double& min, const double& max ) { addToEnd( new MinuitParameter( name, Flag(flag), mean, sigma, min, max ) ); @@ -225,7 +225,7 @@ void MinuitParameterSet::rename(const std::string& name, const std::string& new_ m_keyAccess.emplace(new_name, it); } -MinuitParameter* MinuitParameterSet::addOrGet( const std::string& name, const unsigned int& flag, const double& mean, +MinuitParameter* MinuitParameterSet::addOrGet( const std::string& name, const Flag& flag, const double& mean, const double& sigma, const double& min, const double& max ) { if ( m_keyAccess.count( name ) != 0 ) return m_keyAccess[name]; diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 38579628d12..4fc840d7a33 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -77,7 +77,7 @@ PolarisedSum::PolarisedSum( const EventType& type, } auto d = m_eventType.dim(); - auto p = [&mps](const std::string& name){ return mps.addOrGet(name,2,0,0); }; + auto p = [&mps](const std::string& name){ return mps.addOrGet(name, Flag::Fix, 0, 0); }; if( d.first == 1 ) m_pVector = {}; else if( d.first == 2 ) m_pVector = {p("Px"), p("Py"), p("Pz")}; else if( d.first == 3 ) m_pVector = {p("Px"), p("Py"), p("Pz"), p("Tyy"), p("Tzz"), p("Txy"), p("Txz"), p("Tyz")}; From 80be0f5413a48913a16439ec9fc2cf344483d33f Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 12 Sep 2019 17:38:50 +0200 Subject: [PATCH 101/250] various code changes from cppcheck --- AmpGen/ArgumentPack.h | 2 +- AmpGen/CompiledExpressionBase.h | 2 +- AmpGen/CompilerWrapper.h | 2 +- AmpGen/EventList.h | 12 ++++----- AmpGen/Expression.h | 2 +- AmpGen/Particle.h | 1 + AmpGen/QuarkContent.h | 2 +- AmpGen/Tensor.h | 42 +++++++++++++++---------------- AmpGen/TreeReader.h | 8 +++--- AmpGen/Utilities.h | 4 +-- src/CompiledExpressionBase.cpp | 44 ++++++++++++++++----------------- src/CompilerWrapper.cpp | 7 +++--- src/FitResult.cpp | 16 +++++------- src/Particle.cpp | 31 +++++++++-------------- src/ParticleProperties.cpp | 2 +- src/QuarkContent.cpp | 44 +++++++++++++++------------------ src/ThreeBodyCalculators.cpp | 9 ++++--- src/Utilities.cpp | 2 +- 18 files changed, 107 insertions(+), 125 deletions(-) diff --git a/AmpGen/ArgumentPack.h b/AmpGen/ArgumentPack.h index baeecf25e41..7841581b908 100644 --- a/AmpGen/ArgumentPack.h +++ b/AmpGen/ArgumentPack.h @@ -12,7 +12,7 @@ namespace AmpGen #define DECLARE_ARGUMENT(X, Y) \ struct X : public AmpGen::Argument { \ template \ - X(Z val) : AmpGen::Argument(val){} \ + explicit X(Z val) : AmpGen::Argument(val){} \ X() : AmpGen::Argument(){} \ } /** @class IArgument diff --git a/AmpGen/CompiledExpressionBase.h b/AmpGen/CompiledExpressionBase.h index d857f1d45cc..f4e7997afb4 100644 --- a/AmpGen/CompiledExpressionBase.h +++ b/AmpGen/CompiledExpressionBase.h @@ -55,7 +55,7 @@ namespace AmpGen virtual std::string fcnSignature() const = 0; virtual std::string args() const = 0; virtual void print() const = 0; - virtual ~CompiledExpressionBase() = default; + virtual ~CompiledExpressionBase(); virtual size_t returnTypeSize() const = 0; protected: Expression m_obj; diff --git a/AmpGen/CompilerWrapper.h b/AmpGen/CompilerWrapper.h index 258a80952de..ba62169d6e0 100644 --- a/AmpGen/CompilerWrapper.h +++ b/AmpGen/CompilerWrapper.h @@ -22,7 +22,7 @@ namespace AmpGen void setVerbose() { m_verbose = true ; } void preamble(std::ostream& os ) const ; private: - std::vector m_includes; + std::vector m_includes = {"array","complex","math.h","vector"}; bool m_verbose; std::string m_cxx; std::string generateFilename(); diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 37de375eada..dd9ab8f9fd6 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -94,18 +94,18 @@ namespace AmpGen if ( pdfIndex != m_pdfIndex.end() ) { return pdfIndex->second; } else { - size_t size = m_lastCachePosition; + size_t lcp = m_lastCachePosition; size_t expression_size = size_of == 0 ? expression.returnTypeSize() / sizeof(complex_t) : size_of; - if ( size >= at( 0 ).cacheSize() ) { - WARNING("Cache index " << size << " exceeds cache size = " + if (lcp >= at( 0 ).cacheSize() ) { + WARNING("Cache index " << lcp << " exceeds cache size = " << at(0).cacheSize() << " resizing to " - << size + expression_size ); - resizeCache( size + expression_size ); + << lcp + expression_size ); + resizeCache( lcp + expression_size ); } m_pdfIndex[key] = m_lastCachePosition; m_lastCachePosition += expression_size; - return size; + return lcp; } } diff --git a/AmpGen/Expression.h b/AmpGen/Expression.h index b9856d6d100..fef0e36b8c6 100644 --- a/AmpGen/Expression.h +++ b/AmpGen/Expression.h @@ -62,7 +62,7 @@ #define DECLARE_UNARY_OPERATOR( X ) \ class X : public IUnaryExpression { \ public: \ - X( const Expression& other ); \ + explicit X( const Expression& other ); \ virtual std::string to_string(const ASTResolver* resolver=nullptr) const override; \ virtual Expression d() const override; \ operator Expression() const; \ diff --git a/AmpGen/Particle.h b/AmpGen/Particle.h index b3f9a9a9db1..d40588b554b 100644 --- a/AmpGen/Particle.h +++ b/AmpGen/Particle.h @@ -6,6 +6,7 @@ #include // hack to include optional from https://codereview.stackexchange.com/questions/136350/seamlessly-migrating-experimental-optional-to-optional +#define __cplusplus 201703L #if __cplusplus >= 201703L #include namespace stdx { diff --git a/AmpGen/QuarkContent.h b/AmpGen/QuarkContent.h index a0ac3c32644..7b291ce32e9 100644 --- a/AmpGen/QuarkContent.h +++ b/AmpGen/QuarkContent.h @@ -52,7 +52,7 @@ namespace AmpGen bool operator==( const QuarkContent& rhs ) const; bool operator!=( const QuarkContent& rhs ) const; QuarkState operator[]( const size_t& index) const; - std::vector quarks() const; + const std::vector& quarks() const; }; std::ostream& operator<<( std::ostream& st, const QuarkState& qc ); std::ostream& operator<<( std::ostream& st, const QuarkContent& qc ); diff --git a/AmpGen/Tensor.h b/AmpGen/Tensor.h index 4fb2e95c720..41ca85ac905 100644 --- a/AmpGen/Tensor.h +++ b/AmpGen/Tensor.h @@ -178,27 +178,27 @@ namespace AmpGen Tensor m_tensor; }; - Tensor operator+( const Tensor& t1, const Tensor& t2 ); - Tensor operator-( const Tensor& t1, const Tensor& t2 ); - Tensor operator/( const Tensor& t1, const Expression& t2 ); - Tensor operator*( const Expression& t1, const Tensor& t2 ); - Tensor operator*( const Tensor& t1, const Expression& t2 ); - - Tensor operator/( const Tensor& t1, const double& t2 ); - Tensor operator*( const double& t1, const Tensor& t2 ); - Tensor operator*( const Tensor& t1, const double& t2 ); - - TensorProxy operator*( const TensorProxy& t1, const TensorProxy& t2 ); - TensorProxy operator+( const TensorProxy& t1, const TensorProxy& t2 ); - TensorProxy operator-( const TensorProxy& t1, const TensorProxy& t2 ); - - TensorProxy operator/( const TensorProxy& t1, const Expression& t2 ); - TensorProxy operator*( const Expression& t1, const TensorProxy& t2 ); - TensorProxy operator*( const TensorProxy& t1, const Expression& t2 ); - - TensorProxy operator/( const TensorProxy& t1, const double& t2 ); - TensorProxy operator*( const double& t1, const TensorProxy& t2 ); - TensorProxy operator*( const TensorProxy& t1, const double& t2 ); + Tensor operator+(const Tensor&, const Tensor&); + Tensor operator-(const Tensor&, const Tensor&); + Tensor operator/(const Tensor&, const Expression&); + Tensor operator*(const Expression&, const Tensor&); + Tensor operator*(const Tensor&, const Expression&); + + Tensor operator/(const Tensor&, const double&); + Tensor operator*(const double&, const Tensor&); + Tensor operator*(const Tensor&, const double&); + + TensorProxy operator*(const TensorProxy&, const TensorProxy&); + TensorProxy operator+(const TensorProxy&, const TensorProxy&); + TensorProxy operator-(const TensorProxy&, const TensorProxy&); + + TensorProxy operator/(const TensorProxy&, const Expression& ); + TensorProxy operator*(const Expression& , const TensorProxy&); + TensorProxy operator*(const TensorProxy&, const Expression& ); + + TensorProxy operator/(const TensorProxy&, const double&); + TensorProxy operator*(const double& , const TensorProxy&); + TensorProxy operator*(const TensorProxy&, const double&); Tensor Identity( const size_t& rank = 4 ); diff --git a/AmpGen/TreeReader.h b/AmpGen/TreeReader.h index a71f97d752d..64e9924f8cf 100644 --- a/AmpGen/TreeReader.h +++ b/AmpGen/TreeReader.h @@ -59,12 +59,12 @@ namespace AmpGen bool operator!=( const Iterator& rhs ) const { return m_position != rhs.m_position; } size_t operator*() const { return m_position; } }; - TTree* tree; - bool ready; - std::vector branches; + TTree* tree = {nullptr}; + bool ready = {false}; + std::vector branches = {}; public: - TreeReader( TTree* tree ) : tree( tree ) {} + explicit TreeReader( TTree* tree ) : tree( tree ) {} void setBranch( const std::string& name, OutputType* ptr ) { IReadBranch* new_branch = nullptr; diff --git a/AmpGen/Utilities.h b/AmpGen/Utilities.h index 220698cf6b5..98cc1e0f2e1 100644 --- a/AmpGen/Utilities.h +++ b/AmpGen/Utilities.h @@ -38,7 +38,6 @@ namespace AmpGen { template std::string vectorToString( const std::vector& obj, const std::string& delim = "" ) { - std::string returnValue; std::stringstream ss; if( obj.size() == 0 ) return ""; for ( unsigned int i = 0 ; i < obj.size()-1; ++i ) @@ -50,7 +49,6 @@ namespace AmpGen { template std::string vectorToString( const std::vector& obj, const std::string& delim="", const F& functor =[](const T& f){ return f ; } ) { - std::string returnValue; std::stringstream ss; if( obj.size() == 0 ) return ""; for ( unsigned int i = 0 ; i < obj.size()-1; ++i ) @@ -195,7 +193,7 @@ namespace AmpGen { bool isDir( const std::string& fname ); bool fileExists( const std::string& name ); - std::vector getListOfFiles(const std::string& directory, std::string patternString = ""); + std::vector getListOfFiles(const std::string& directory, const std::string& patternString = ""); void printSplash(); void printReleaseNotes(const std::string& fname); diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index 6368a5e5880..220231a89ea 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -14,6 +14,26 @@ #include "AmpGen/ProfileClock.h" using namespace AmpGen; +CompiledExpressionBase::CompiledExpressionBase( const Expression& expression, + const std::string& name, + const DebugSymbols& db, + const std::map& evtMapping ) + : m_obj( expression ), + m_name( name ), + m_progName( programatic_name(name) ), + m_db(db), + m_evtMap(evtMapping) {} + +CompiledExpressionBase::CompiledExpressionBase( const std::string& name ) + : m_name( name ), + m_progName( programatic_name(name) ) {} + + +CompiledExpressionBase::~CompiledExpressionBase() +{ + if( m_resolver != nullptr ) delete m_resolver; +} + std::string AmpGen::programatic_name( std::string s ) { std::replace( s.begin(), s.end(), '-', 'm' ); @@ -28,43 +48,23 @@ std::string AmpGen::programatic_name( std::string s ) void CompiledExpressionBase::resolve(const MinuitParameterSet* mps) { - ProfileClock pc; if( m_resolver != nullptr ) delete m_resolver ; m_resolver = new ASTResolver( m_evtMap, mps ); m_dependentSubexpressions = m_resolver->getOrderedSubExpressions( m_obj ); for ( auto& sym : m_db ){ auto expressions_for_this = m_resolver->getOrderedSubExpressions( sym.second); for( auto& it : expressions_for_this ){ - bool isAlreadyInStack = false; - for( auto& jt : m_debugSubexpressions ){ - if( it.first == jt.first ){ isAlreadyInStack = true; break ; } - } - if( !isAlreadyInStack ) m_debugSubexpressions.push_back( it ); + auto is_same = [&it](const auto& jt){ return it.first == jt.first ; }; + if( !std::any_of( m_debugSubexpressions.begin(), m_debugSubexpressions.end(), is_same) ) m_debugSubexpressions.push_back( it ); } } m_cacheTransfers.clear(); for( auto& expression : m_resolver->cacheFunctions() ) m_cacheTransfers.emplace_back( expression.second ); resizeExternalCache( m_resolver->nParams() ); - pc.stop(); - //INFO("Took: " << pc << " ms to resolve tree"); prepare(); } -CompiledExpressionBase::CompiledExpressionBase( const Expression& expression, - const std::string& name, - const DebugSymbols& db, - const std::map& evtMapping ) - : m_obj( expression ), - m_name( name ), - m_progName( programatic_name(name) ), - m_db(db), - m_evtMap(evtMapping) {} - -CompiledExpressionBase::CompiledExpressionBase( const std::string& name ) - : m_name( name ), - m_progName( programatic_name(name) ) {} - std::string CompiledExpressionBase::name() const { return m_name; } std::string CompiledExpressionBase::progName() const { return m_progName; } unsigned int CompiledExpressionBase::hash() const { return FNV1a_hash(m_name); } diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index 6a3b63abbb5..66e503732e8 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -22,11 +22,10 @@ using namespace AmpGen; -CompilerWrapper::CompilerWrapper( const bool& verbose ) : - m_includes( {"array", "complex", "math.h", "vector"} ), - m_verbose(verbose) +CompilerWrapper::CompilerWrapper( const bool& verbose ) : + m_verbose(verbose), + m_cxx(getenv("CXX") != nullptr ? std::string( getenv( "CXX" ) ) : "") { - m_cxx = getenv("CXX") != nullptr ? std::string( getenv( "CXX" ) ) : ""; if ( m_cxx == "" ) { #ifdef AMPGEN_CXX if( m_verbose ) diff --git a/src/FitResult.cpp b/src/FitResult.cpp index 7142fadc55b..089d451876a 100644 --- a/src/FitResult.cpp +++ b/src/FitResult.cpp @@ -34,9 +34,8 @@ FitResult::FitResult( const FitResult& other ) , m_status( other.status() ) , m_observables( other.observables() ) , m_fitFractions( other.fitFractions() ) + , m_covarianceMatrix(other.cov()) { - m_covarianceMatrix.ResizeTo( other.cov().GetNrows(), other.cov().GetNcols() ); - m_covarianceMatrix = other.cov(); } FitResult::FitResult( const std::string& filename ) : @@ -46,14 +45,11 @@ FitResult::FitResult( const std::string& filename ) : } FitResult::FitResult( const Minimiser& mini ) -{ - m_mps = std::make_shared( *mini.parSet() ); - m_LL = mini.FCN(); - auto M = mini.covMatrixFull(); - m_covarianceMatrix.ResizeTo( M.GetNcols(), M.GetNrows() ); - m_covarianceMatrix = M; - m_status = mini.status(); - m_nParam = 0; + : m_mps ( std::make_shared( *mini.parSet() ) ) + , m_LL ( mini.FCN() ) + , m_nParam( 0 ) + , m_status( mini.status() ) + , m_covarianceMatrix( mini.covMatrixFull() ) { for (size_t i = 0; i < m_mps->size(); ++i ) { if ( m_mps->at(i)->isFree() ) m_nParam++; m_covMapping[ m_mps->at(i)->name() ] = i; diff --git a/src/Particle.cpp b/src/Particle.cpp index ab538d8f6db..765a936bcb5 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -31,23 +31,20 @@ using namespace AmpGen; using namespace std::complex_literals; Particle::Particle() -{ - m_defaultModifier = NamedParameter("Particle::DefaultModifier","", "Default modifier to use for lineshapes, for example to use normalised vs unnormalised Blatt-Weisskopf factors."); - m_spinFormalism = NamedParameter("Particle::SpinFormalism" ,"Covariant", "Spin formalism to use, can choose between Covariant and Canonical formalisms"); - m_spinBasis = NamedParameter("Particle::SpinBasis" ,"Dirac", + : m_spinFormalism { NamedParameter("Particle::SpinFormalism" ,"Covariant", "Spin formalism to use, can choose between Covariant and Canonical formalisms") } + , m_spinBasis { NamedParameter("Particle::SpinBasis" ,"Dirac", optionalHelpString("Basis to use for calculating external polarisation tensors / spinors.", { {"Dirac", "Quantises along the z-axis"} - , {"Weyl" , "Quantises along the direction of motion"}} ) ); - -} + , {"Weyl" , "Quantises along the direction of motion"}} ) )} + , m_defaultModifier { NamedParameter("Particle::DefaultModifier","", "Default modifier to use for lineshapes, for example to use normalised vs unnormalised Blatt-Weisskopf factors.") } + {} Particle::Particle( const std::string& name, const Particle& p1, const Particle& p2 ) : Particle() { m_props = ParticlePropertiesList::get( name ); m_name = name; - m_daughters.push_back(std::make_shared(p1)); - m_daughters.push_back(std::make_shared(p2)); + m_daughters = { std::make_shared(p1), std::make_shared(p2) }; pdgLookup(); sortDaughters(); for ( auto& d : m_daughters ) d->setTop( false ); @@ -58,8 +55,7 @@ Particle::Particle( const int& pdgID, const Particle& p1, const Particle& p2 ) : Particle() { m_props = ParticlePropertiesList::get( pdgID ); - m_daughters.push_back( std::make_shared( p1 ) ); - m_daughters.push_back( std::make_shared( p2 ) ); + m_daughters = {std::make_shared( p1 ) , std::make_shared( p2 ) }; if ( m_props != nullptr ) m_name = m_props->name(); pdgLookup(); sortDaughters(); @@ -102,13 +98,7 @@ Particle::Particle( const std::string& decayString, const std::vector exchangeParities; - for( auto& p : finalStateParticles ) exchangeParities.push_back( p->props()->isFermion() ? -1 : 1 ); + std::transform( finalStateParticles.begin(), finalStateParticles.end(), std::back_inserter(exchangeParities), + [](const auto& p){ return p->props()->isFermion() ? -1 : 1; } ); for(auto& ordering : orderings){ auto exchangeParity = minSwaps( ordering, exchangeParities ); setOrdering( ordering ); @@ -751,7 +742,7 @@ EventType Particle::eventType() const { std::vector names = {m_name}; auto fs = getFinalStateParticles( false ); - for ( auto& p : fs ) names.push_back( p->name() ); + std::transform(fs.begin(), fs.end(), std::back_inserter(names), [](const auto& p){ return p->name(); } ); return EventType( names ); } diff --git a/src/ParticleProperties.cpp b/src/ParticleProperties.cpp index c5ad46bc041..1d0cef7a40b 100644 --- a/src/ParticleProperties.cpp +++ b/src/ParticleProperties.cpp @@ -46,7 +46,7 @@ ParticleProperties::ParticleProperties( const std::string& pdg_string ) : m_netQ DEBUG( "Invalid line : " << pdg_string ); return; } - for ( auto& st : s ) st = trim( st ); + std::transform(s.begin(), s.end(), s.begin(), trim); bool status = 1; m_mass = lexical_cast( s[0], status ); m_mErrPlus = lexical_cast( s[1], status ); diff --git a/src/QuarkContent.cpp b/src/QuarkContent.cpp index 6ced6629638..4211402a858 100644 --- a/src/QuarkContent.cpp +++ b/src/QuarkContent.cpp @@ -39,7 +39,6 @@ bool QuarkState::initPositions() void QuarkState::antiThis() { std::transform( m_quarks.begin(), m_quarks.end(), m_quarks.begin(), [](const auto& quark){ return (-1)*quark ; } ); -// for ( auto& quark : m_quarks ) quark *= -1; } char QuarkState::nameFromPosition( int i ) const @@ -83,16 +82,9 @@ QuarkState QuarkState::operator-( const QuarkState& rhs ) const returnVal -= rhs; return returnVal; } -std::ostream& operator<<( std::ostream& st, const QuarkState& qc ) -{ - qc.print( st ); - return st; -} bool QuarkState::isVacuum() const { - for ( auto& quark : m_quarks ) - if ( quark != 0 ) return false; - return true; + return std::all_of( m_quarks.begin(), m_quarks.end(), [](const auto& quark){ return quark == 0 ; } ); } bool QuarkState::operator==( const QuarkState& rhs ) const @@ -184,23 +176,14 @@ QuarkContent QuarkContent::operator-( const QuarkContent& rhs ) const returnVal -= rhs; return returnVal; } -std::ostream& AmpGen::operator<<( std::ostream& st, const QuarkContent& qc ) -{ - qc.print( st ); - return st; -} bool QuarkContent::operator==( const QuarkContent& rhs ) const { -// return std::any_of( m_quarks.begin(), m_quarks.end(), [rhs](auto& ql){ -// return std::any_of( rhs.quarks().begin(), rhs.quarks().end(), -// [ql](auto& qr){ return ql == qr; } ) ;} ); - for ( auto& l : m_quarks ) { - for ( auto& r : rhs.quarks() ) { - if ( l == r ) return true; - } - } - return false; + for ( auto& qsl : m_quarks ) { + bool isSame = std::any_of( rhs.quarks().begin(), rhs.quarks().end(), [&qsl](auto& qsr){ return qsl == qsr; } ); + if( isSame ) return true; + } + return false; } bool QuarkContent::operator!=( const QuarkContent& rhs ) const @@ -215,8 +198,21 @@ QuarkState QuarkContent::operator[]( const size_t& index ) const size_t QuarkContent::size() const { return m_quarks.size(); } -std::vector QuarkContent::quarks() const +const std::vector& QuarkContent::quarks() const { return m_quarks; } + +std::ostream& AmpGen::operator<<( std::ostream& st, const QuarkContent& qc ) +{ + qc.print( st ); + return st; +} + +std::ostream& AmpGen::operator<<( std::ostream& st, const QuarkState& qc ) +{ + qc.print( st ); + return st; +} + diff --git a/src/ThreeBodyCalculators.cpp b/src/ThreeBodyCalculators.cpp index d3123d52aab..fc7d1b9aa29 100644 --- a/src/ThreeBodyCalculators.cpp +++ b/src/ThreeBodyCalculators.cpp @@ -164,6 +164,7 @@ Expression ThreeBodyCalculator::PartialWidth::spinAverageMatrixElement( ThreeBodyCalculator::ThreeBodyCalculator( const std::string& head, MinuitParameterSet& mps, const size_t& nKnots, const double& min, const double& max) : m_min(min), m_max(max), + m_norm(1), m_nKnots(nKnots), m_name(head), m_mps(&mps) @@ -225,10 +226,10 @@ TGraph* ThreeBodyCalculator::widthGraph( const double& mNorm ) return g; } -ThreeBodyCalculator::PartialWidth::PartialWidth( const EventType& evt, MinuitParameterSet& mps ) : - fcs( evt, mps, "" ) - , integrator(1, evt.mass(0)*evt.mass(0), evt.mass(1)*evt.mass(1) , evt.mass(2)*evt.mass(2) ) - , type(evt) +ThreeBodyCalculator::PartialWidth::PartialWidth( const EventType& evt, MinuitParameterSet& mps ) + : fcs( evt, mps, "" ) + , integrator(1, evt.mass(0)*evt.mass(0), evt.mass(1)*evt.mass(1) , evt.mass(2)*evt.mass(2) ) + , type(evt) { DebugSymbols msym; Expression matrixElementTotal = spinAverageMatrixElement( fcs.matrixElements(), &msym ); diff --git a/src/Utilities.cpp b/src/Utilities.cpp index 2d0768ebf47..d01087d4b32 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -342,7 +342,7 @@ bool AmpGen::isDir( const std::string& pathname ) return stat( pathname.c_str(), &sb ) == 0 && S_ISDIR( sb.st_mode ); } -std::vector AmpGen::getListOfFiles( const std::string& directory, std::string patternString ) +std::vector AmpGen::getListOfFiles( const std::string& directory, const std::string& patternString ) { std::string expanded_path = expandGlobals( directory ); std::vector files; From a12c300b03528f789a22f25f4f53b14f2221381c Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 13 Sep 2019 13:20:29 +0200 Subject: [PATCH 102/250] fix double-free in ASTResolver --- AmpGen/ASTResolver.h | 6 ++---- AmpGen/AmplitudeRules.h | 10 +++------- AmpGen/CompiledExpressionBase.h | 7 +++---- AmpGen/ExpressionParser.h | 1 + AmpGen/Particle.h | 1 - src/ASTResolver.cpp | 11 ++++++++++- src/CoherentSum.cpp | 2 +- src/CompiledExpressionBase.cpp | 23 ++++++++++------------- src/ExpressionParser.cpp | 4 ++++ 9 files changed, 34 insertions(+), 31 deletions(-) diff --git a/AmpGen/ASTResolver.h b/AmpGen/ASTResolver.h index 3b52df3416d..62a80d0e866 100644 --- a/AmpGen/ASTResolver.h +++ b/AmpGen/ASTResolver.h @@ -29,7 +29,6 @@ namespace AmpGen { { public: ASTResolver(const std::map& evtMap = {} , const MinuitParameterSet* mps = nullptr ); - void cleanup(); std::vector> getOrderedSubExpressions( const Expression& expression); template void resolve( const TYPE& obj ){} @@ -49,7 +48,7 @@ namespace AmpGen { void addResolvedParameter(const IExpression* param, const std::string& thing); void addResolvedParameter(const IExpression* param, const size_t& address, const size_t& arg=0); std::string resolvedParameter( const IExpression* param ) const; - + void clear(); private: std::map m_resolvedParameters; /// Map of parameters that have been resolved std::map> m_cacheFunctions; /// Container of functions for calculating function cache @@ -59,8 +58,7 @@ namespace AmpGen { std::map m_tempTrees; /// temporary store of sub-trees for performing cse reduction unsigned int m_nParameters; /// Number of parameters bool m_enable_cuda; /// flag to generate CUDA code <> - bool m_enable_compileTimeConstants; /// flag to enable compile time constants <> - + bool m_enable_compileTimeConstants; /// flag to enable compile time constants <> }; template <> void ASTResolver::resolve( const Parameter& obj ); diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index 68ce3866222..e03a01eeafb 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -91,13 +91,8 @@ namespace AmpGen const std::map& evtFormat, const bool& debugThis=false) : decayTree(dt), - coupling(coupling) - { - DebugSymbols db; - auto expression = dt.getExpression(debugThis ? &db : nullptr); - amp = CompiledExpression - (expression, dt.decayDescriptor(), evtFormat, debugThis ? db : DebugSymbols(), &mps ); - } + coupling(coupling), + amp(decayTree.getExpression(debugThis ? &db : nullptr ), decayTree.decayDescriptor(), evtFormat, db, &mps ) {} const RT operator()(const Event& event) const { return amp(event.address() ); } const RT operator()(const Event& event, const size_t& cacheOffset) const { return amp(event.address() + cacheOffset); } @@ -106,6 +101,7 @@ namespace AmpGen Particle decayTree; CouplingConstant coupling; complex_t coefficient; + DebugSymbols db; CompiledExpression amp; size_t addressData = {999}; }; diff --git a/AmpGen/CompiledExpressionBase.h b/AmpGen/CompiledExpressionBase.h index f4e7997afb4..d7ee330e9cb 100644 --- a/AmpGen/CompiledExpressionBase.h +++ b/AmpGen/CompiledExpressionBase.h @@ -18,10 +18,9 @@ namespace AmpGen class CacheTransfer; std::string programatic_name( std::string s ); - + class ASTResolver; class MinuitParameter; class MinuitParameterSet; - class ASTResolver; /** @class CompiledExpressionBase * Base class for compiled expressions, i.e. expressions that are (almost) ready to be evaluated. @@ -37,7 +36,7 @@ namespace AmpGen const DebugSymbols& db=DebugSymbols(), const std::map& evtMapping = {} ); CompiledExpressionBase( const std::string& name ); - CompiledExpressionBase() = default; + CompiledExpressionBase(); void resolve(const MinuitParameterSet* mps = nullptr); void prepare(); @@ -66,7 +65,7 @@ namespace AmpGen std::vector> m_dependentSubexpressions; std::vector> m_debugSubexpressions; std::vector> m_cacheTransfers; - ASTResolver* m_resolver = {nullptr}; + std::shared_ptr m_resolver; private: void addDebug( std::ostream& stream ) const; diff --git a/AmpGen/ExpressionParser.h b/AmpGen/ExpressionParser.h index 01c336ca3d9..73e379debd2 100644 --- a/AmpGen/ExpressionParser.h +++ b/AmpGen/ExpressionParser.h @@ -24,6 +24,7 @@ namespace AmpGen complex_t operator()() const override ; operator Expression() const ; std::string name() const; + const MinuitParameter& param() const; private: MinuitParameter* m_parameter; }; diff --git a/AmpGen/Particle.h b/AmpGen/Particle.h index d40588b554b..b3f9a9a9db1 100644 --- a/AmpGen/Particle.h +++ b/AmpGen/Particle.h @@ -6,7 +6,6 @@ #include // hack to include optional from https://codereview.stackexchange.com/questions/136350/seamlessly-migrating-experimental-optional-to-optional -#define __cplusplus 201703L #if __cplusplus >= 201703L #include namespace stdx { diff --git a/src/ASTResolver.cpp b/src/ASTResolver.cpp index 5d6c1a021ee..1faaf6f6ea1 100644 --- a/src/ASTResolver.cpp +++ b/src/ASTResolver.cpp @@ -146,7 +146,16 @@ std::string ASTResolver::resolvedParameter( const IExpression* param ) const auto it = m_resolvedParameters.find(param); if( it != m_resolvedParameters.end() ) return it->second; else { - ERROR( "Parameter cannot be resolved" << param ); + ERROR( "Parameter cannot be resolved: [" << this << "]" << param ); return ""; } } + +void ASTResolver::clear() +{ + m_resolvedParameters.clear(); + m_cacheFunctions.clear(); + m_parameterMapping.clear(); + m_tempTrees.clear(); + m_nParameters = 0; +} diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index b0487ec794c..0f0f7045ef6 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -53,7 +53,7 @@ CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, m_matrixElements[i] = TransitionMatrix( amplitudes[i].first, amplitudes[i].second, mps, this->m_evtType.getEventFormat(), this->m_dbThis); CompilerWrapper().compile( m_matrixElements[i].amp, this->m_objCache); } ); } - m_isConstant = false ; + m_isConstant = false; } void updateCache(EventList* events, TransitionMatrix& me, const size_t& sizeMax) diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index 220231a89ea..b4d0c255e17 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -22,17 +22,15 @@ CompiledExpressionBase::CompiledExpressionBase( const Expression& expression, m_name( name ), m_progName( programatic_name(name) ), m_db(db), - m_evtMap(evtMapping) {} + m_evtMap(evtMapping){} CompiledExpressionBase::CompiledExpressionBase( const std::string& name ) : m_name( name ), m_progName( programatic_name(name) ) {} +CompiledExpressionBase::CompiledExpressionBase() = default; -CompiledExpressionBase::~CompiledExpressionBase() -{ - if( m_resolver != nullptr ) delete m_resolver; -} +CompiledExpressionBase::~CompiledExpressionBase() {} std::string AmpGen::programatic_name( std::string s ) { @@ -48,8 +46,7 @@ std::string AmpGen::programatic_name( std::string s ) void CompiledExpressionBase::resolve(const MinuitParameterSet* mps) { - if( m_resolver != nullptr ) delete m_resolver ; - m_resolver = new ASTResolver( m_evtMap, mps ); + if( m_resolver == nullptr ) m_resolver = std::make_shared( m_evtMap, mps ); m_dependentSubexpressions = m_resolver->getOrderedSubExpressions( m_obj ); for ( auto& sym : m_db ){ auto expressions_for_this = m_resolver->getOrderedSubExpressions( sym.second); @@ -77,7 +74,7 @@ void CompiledExpressionBase::prepare() void CompiledExpressionBase::addDependentExpressions( std::ostream& stream, size_t& sizeOfStream ) const { for ( auto& dep : m_dependentSubexpressions ) { - std::string rt = " auto v" + std::to_string(dep.first) + " = " + dep.second.to_string(m_resolver) +";"; + std::string rt = " auto v" + std::to_string(dep.first) + " = " + dep.second.to_string(m_resolver.get()) +";"; stream << rt << "\n"; sizeOfStream += sizeof(char) * rt.size(); /// bytes /// } @@ -93,13 +90,13 @@ void CompiledExpressionBase::to_stream( std::ostream& stream ) const // stream << "#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wreturn-type-c-linkage\"\n"; stream << "extern \"C\" " << returnTypename() << " " << progName() << "(" << fcnSignature() << "){\n"; addDependentExpressions( stream , sizeOfStream ); - stream << "return " << m_obj.to_string(m_resolver) << ";\n}\n"; + stream << "return " << m_obj.to_string(m_resolver.get()) << ";\n}\n"; } else { stream << "__global__ void " << progName() << "( " << returnTypename() + "* r, const int N, " << fcnSignature() << "){\n"; stream << " int i = blockIdx.x * blockDim.x + threadIdx.x;\n"; addDependentExpressions( stream, sizeOfStream); - stream << " r[i] = " << m_obj.to_string(m_resolver) << ";\n}\n"; + stream << " r[i] = " << m_obj.to_string(m_resolver.get()) << ";\n}\n"; } if( NamedParameter("IncludePythonBindings", false) == true && returnTypename().find("complex") != std::string::npos ){ @@ -130,7 +127,7 @@ void CompiledExpressionBase::addDebug( std::ostream& stream ) const stream << "extern \"C\" std::vector>> " << m_progName << "_DB(" << fcnSignature() << "){\n"; for ( auto& dep : m_debugSubexpressions ) { - std::string rt = "auto v" + std::to_string(dep.first) + " = " + dep.second.to_string(m_resolver) +";"; + std::string rt = "auto v" + std::to_string(dep.first) + " = " + dep.second.to_string(m_resolver.get()) +";"; stream << rt << "\n"; } stream << "return {"; @@ -138,8 +135,8 @@ void CompiledExpressionBase::addDebug( std::ostream& stream ) const std::string comma = (i!=m_db.size()-1)?", " :"};\n}\n"; const auto expression = m_db[i].second; stream << std::endl << "{\"" << m_db[i].first << "\","; - if ( expression.to_string(m_resolver) != "NULL" ) - stream << expression.to_string(m_resolver) << "}" << comma; + if ( expression.to_string(m_resolver.get()) != "NULL" ) + stream << expression.to_string(m_resolver.get()) << "}" << comma; else stream << "-999}" << comma ; } } diff --git a/src/ExpressionParser.cpp b/src/ExpressionParser.cpp index 0c541285144..5562c5d60a1 100644 --- a/src/ExpressionParser.cpp +++ b/src/ExpressionParser.cpp @@ -172,6 +172,10 @@ complex_t MinuitParameterLink::operator()() const return m_parameter->mean(); } +const MinuitParameter& MinuitParameterLink::param() const { + return *m_parameter ; +} + ExpressionPack::ExpressionPack( const Expression& A, const Expression& B ) { auto c1 = dynamic_cast( A.get() ); From cf5c401e190bcb35eacaad0d2806e7244bde9812 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 24 Sep 2019 14:43:07 +0200 Subject: [PATCH 103/250] changes from cppcheck, many size_t -> unsigned's --- AmpGen/ASTResolver.h | 4 +- AmpGen/AmplitudeRules.h | 2 +- AmpGen/ArgumentPack.h | 7 +- AmpGen/BinDT.h | 35 +++--- AmpGen/CompiledExpression.h | 6 +- AmpGen/CompiledExpressionBase.h | 8 +- AmpGen/CompilerWrapper.h | 2 +- AmpGen/ErrorPropagator.h | 4 +- AmpGen/Event.h | 54 ++++----- AmpGen/EventType.h | 28 ++--- AmpGen/ExpressionParser.h | 4 +- AmpGen/FastDT.h | 18 +-- AmpGen/FitResult.h | 6 +- AmpGen/Generator.h | 4 +- AmpGen/Kinematics.h | 20 ++-- AmpGen/Lineshapes.h | 6 +- AmpGen/MetaUtils.h | 10 +- AmpGen/MsgService.h | 1 - AmpGen/NamedParameter.h | 1 - AmpGen/Particle.h | 22 ++-- AmpGen/ParticleProperties.h | 2 +- AmpGen/ParticlePropertiesList.h | 2 +- AmpGen/Projection.h | 20 ++-- AmpGen/QuarkContent.h | 6 +- AmpGen/RecursivePhaseSpace.h | 25 ++-- AmpGen/SumPDF.h | 2 +- AmpGen/Tensor.h | 85 +++++++------- AmpGen/ThreadPool.h | 5 +- AmpGen/Utilities.h | 18 +-- AmpGen/Wigner.h | 12 +- AmpGen/kMatrix.h | 6 +- apps/Generator.cpp | 8 +- examples/FitterWithPolarisation.cpp | 3 +- examples/QcGenerator.cpp | 4 +- examples/SignalOnlyFitter.cpp | 7 +- examples/modern.cpp | 173 ++++++++++++++++++++++++++++ src/ASTResolver.cpp | 2 +- src/BinDT.cpp | 11 +- src/CompiledExpressionBase.cpp | 18 +-- src/CompilerWrapper.cpp | 2 +- src/Event.cpp | 36 +++--- src/EventType.cpp | 58 +++++----- src/FastDT.cpp | 7 +- src/Kinematics.cpp | 18 +-- src/Lineshapes/CoupledChannel.cpp | 8 +- src/Lineshapes/GenericKmatrix.cpp | 24 ++-- src/Lineshapes/kMatrix.cpp | 14 +-- src/Particle.cpp | 6 +- src/ParticleProperties.cpp | 2 +- src/ParticlePropertiesList.cpp | 2 +- src/Plots.cpp | 2 - src/PolarisedSum.cpp | 4 +- src/QuarkContent.cpp | 30 ++--- src/Spline.cpp | 1 + src/Tensor.cpp | 168 +++++++++++++-------------- src/Utilities.cpp | 2 +- src/Vertex.cpp | 2 +- src/Wigner.cpp | 2 +- 58 files changed, 594 insertions(+), 445 deletions(-) create mode 100644 examples/modern.cpp diff --git a/AmpGen/ASTResolver.h b/AmpGen/ASTResolver.h index 62a80d0e866..95287ad207b 100644 --- a/AmpGen/ASTResolver.h +++ b/AmpGen/ASTResolver.h @@ -28,7 +28,7 @@ namespace AmpGen { class ASTResolver { public: - ASTResolver(const std::map& evtMap = {} , const MinuitParameterSet* mps = nullptr ); + ASTResolver(const std::map& evtMap = {} , const MinuitParameterSet* mps = nullptr ); std::vector> getOrderedSubExpressions( const Expression& expression); template void resolve( const TYPE& obj ){} @@ -52,7 +52,7 @@ namespace AmpGen { private: std::map m_resolvedParameters; /// Map of parameters that have been resolved std::map> m_cacheFunctions; /// Container of functions for calculating function cache - std::map m_evtMap; /// Event specification + std::map m_evtMap; /// Event specification std::map m_parameterMapping; /// Mapping of parameters to compile parameters const MinuitParameterSet* m_mps; /// Set of MinuitParameters std::map m_tempTrees; /// temporary store of sub-trees for performing cse reduction diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index e03a01eeafb..f73e2508c85 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -88,7 +88,7 @@ namespace AmpGen TransitionMatrix(Particle& dt, const CouplingConstant& coupling, const MinuitParameterSet& mps, - const std::map& evtFormat, + const std::map& evtFormat, const bool& debugThis=false) : decayTree(dt), coupling(coupling), diff --git a/AmpGen/ArgumentPack.h b/AmpGen/ArgumentPack.h index 7841581b908..c1decb23862 100644 --- a/AmpGen/ArgumentPack.h +++ b/AmpGen/ArgumentPack.h @@ -55,7 +55,7 @@ namespace AmpGen struct Argument : public IArgument { template - Argument( T x ) : val(x) {} + explicit Argument( T x ) : val(x) {} Argument() = default; operator TYPE() const { return val; } TYPE val = { TYPE() }; @@ -71,10 +71,10 @@ namespace AmpGen { public: template - ArgumentPack( const ARGS&... args ) + explicit ArgumentPack( const ARGS&... args ) { std::tuple argTuple( args... ); - for_each( argTuple, [this]( auto& f ) { m_parameters.emplace_back( makeShared( f ) ); } ); + for_each(argTuple, [this](const auto& f){ this->addArgument(f) ; } ); } template ARG getArg( const DEFAULT_TYPE& default_argument = DEFAULT_TYPE() ) const @@ -87,6 +87,7 @@ namespace AmpGen } private: std::vector> m_parameters; + template void addArgument( const T& f ){ m_parameters.emplace_back( std::make_shared(f) ) ; } }; } // namespace AmpGen diff --git a/AmpGen/BinDT.h b/AmpGen/BinDT.h index 2c35c0aca6a..58795770a6a 100644 --- a/AmpGen/BinDT.h +++ b/AmpGen/BinDT.h @@ -102,11 +102,10 @@ namespace AmpGen INFO( "Making nodes" ); m_top = makeNodes( addresses ); } - BinDT( const ArgumentPack& args ); + explicit BinDT( const ArgumentPack& args ); BinDT() = default; std::shared_ptr top() { return m_top; } - double nnUniformity( std::vector evts, const unsigned int& index ) const; unsigned int getBinNumber( const Event& evt ) const; unsigned int getBinNumber( const double* evt ) const; unsigned int getBin( const Event& evt ) const; @@ -115,32 +114,28 @@ namespace AmpGen void readFromStream( std::istream& stream ); void serialize( std::ofstream& output ); void serialize( const std::string& filename ); - void setQueueOrdering( const std::vector& queueOrdering ){ m_queueOrdering = queueOrdering ; } + void setQueueOrdering( const std::vector& queueOrdering ){ m_queueOrdering = queueOrdering ; } std::vector>& nodes() { return m_endNodes; } const std::vector>& const_nodes() const { return m_endNodes; } std::vector>::iterator begin() { return m_endNodes.begin(); } std::vector>::iterator end() { return m_endNodes.end(); } std::function( const Event& )> makeDefaultFunctors(); - void refreshQueue( const std::vector& evts, std::queue& indexQueue, - const unsigned int& depth ); - std::shared_ptr makeNodes( std::vector evts, std::queue indexQueue, - const unsigned int& depth ); - std::shared_ptr makeNodes( std::vector evts ); - std::shared_ptr makeNodes( std::vector source, std::vector target ); - - std::shared_ptr makeNodes( std::vector source, std::vector target, - std::queue indexQueue, const unsigned int& depth ); - void setFunctor( const std::function( const Event& )>& functors ) { m_functors = functors; } + void refreshQueue(const std::vector&, std::queue&, const unsigned&); + std::shared_ptr makeNodes(const std::vector&, std::queue, const unsigned&); + std::shared_ptr makeNodes(const std::vector&); + std::shared_ptr makeNodes(const std::vector&, const std::vector&); + std::shared_ptr makeNodes(std::vector, std::vector, std::queue, const unsigned&); + void setFunctor(const std::function( const Event& )>& functors) { m_functors = functors; } private: - std::shared_ptr m_top; - unsigned int m_dim; - std::vector> m_endNodes; - std::function( const Event& )> m_functors; - unsigned int m_minEvents; - unsigned int m_maxDepth; - std::vector m_queueOrdering; + std::shared_ptr m_top = {nullptr}; + unsigned m_dim = {0}; + unsigned m_minEvents = {0}; + unsigned m_maxDepth = {0}; + std::vector m_queueOrdering = {}; + std::vector> m_endNodes = {}; + std::function(const Event&)> m_functors = {}; double getBestPost(const std::vector& source, const std::vector& target, int index, bool verbose = false ); }; diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index 326fe08b919..43d18aae373 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -36,8 +36,8 @@ namespace AmpGen CompiledExpression( const Expression& expression, const std::string& name, - const std::map& evtMapping = - std::map(), + const std::map& evtMapping = + std::map(), const DebugSymbols& db = {}, const MinuitParameterSet* mps = nullptr ) : CompiledExpressionBase( expression, name, db, evtMapping ) @@ -224,7 +224,7 @@ namespace AmpGen CompiledExpression make_expression( const Expression& expression, const std::string& name, - const std::map & evtMap, + const std::map & evtMap, const MinuitParameterSet& mps ) { CompiledExpression rt(expression,name,evtMap,{},&mps); diff --git a/AmpGen/CompiledExpressionBase.h b/AmpGen/CompiledExpressionBase.h index d7ee330e9cb..97e7c245b73 100644 --- a/AmpGen/CompiledExpressionBase.h +++ b/AmpGen/CompiledExpressionBase.h @@ -31,12 +31,12 @@ namespace AmpGen class CompiledExpressionBase { public: + CompiledExpressionBase(); + CompiledExpressionBase( const std::string& name ); CompiledExpressionBase( const Expression& expression, const std::string& name, const DebugSymbols& db=DebugSymbols(), - const std::map& evtMapping = {} ); - CompiledExpressionBase( const std::string& name ); - CompiledExpressionBase(); + const std::map& evtMapping = {} ); void resolve(const MinuitParameterSet* mps = nullptr); void prepare(); @@ -61,7 +61,7 @@ namespace AmpGen std::string m_name; std::string m_progName; DebugSymbols m_db; - std::map m_evtMap; + std::map m_evtMap; std::vector> m_dependentSubexpressions; std::vector> m_debugSubexpressions; std::vector> m_cacheTransfers; diff --git a/AmpGen/CompilerWrapper.h b/AmpGen/CompilerWrapper.h index ba62169d6e0..0dcbc738147 100644 --- a/AmpGen/CompilerWrapper.h +++ b/AmpGen/CompilerWrapper.h @@ -14,7 +14,7 @@ namespace AmpGen class CompilerWrapper { public: - CompilerWrapper( const bool& verbose=false); + explicit CompilerWrapper( const bool& verbose=false); void generateSource( const CompiledExpressionBase& expression, const std::string& fname); bool compile( CompiledExpressionBase& expression, const std::string& fname=""); bool compile( std::vector& expression, const std::string& fname=""); diff --git a/AmpGen/ErrorPropagator.h b/AmpGen/ErrorPropagator.h index 8a73df91f8b..1178c74badb 100644 --- a/AmpGen/ErrorPropagator.h +++ b/AmpGen/ErrorPropagator.h @@ -38,9 +38,9 @@ namespace AmpGen { public: ///< Constructor for LinearErrorPropagator taking a vector of free parameters, assumes a diagonal covariance matrix taking the parameter uncertainties. - LinearErrorPropagator( const std::vector& params ); + explicit LinearErrorPropagator( const std::vector& params ); ///< Constructor for LinearErrorPropagator, taking a MinuitParameterSet as argument, assumes a diagonal coviarance matrix using the uncertainties on parameters. - LinearErrorPropagator( const MinuitParameterSet& params ); + explicit LinearErrorPropagator( const MinuitParameterSet& params ); ///< Constructor for LinearErrorPropagator, taking a covariance matrix and a vector parameters LinearErrorPropagator( const TMatrixD& reducedCovarianceMatrix, const std::vector& params ); diff --git a/AmpGen/Event.h b/AmpGen/Event.h index 36c269c7404..53e2aed3d18 100644 --- a/AmpGen/Event.h +++ b/AmpGen/Event.h @@ -18,39 +18,39 @@ namespace AmpGen { class Event { public: - Event( const size_t& N, const size_t& cacheSize=0 ); - Event( const real_t* data, const size_t& N, const size_t& cacheSize=0); + Event( const unsigned& N, const unsigned& cacheSize=0 ); + Event( const real_t* data, const unsigned& N, const unsigned& cacheSize=0); - void set( const size_t& i, const std::vector& p ); - void set( const size_t& i, const real_t* p ); + void set( const unsigned& i, const std::vector& p ); + void set( const unsigned& i, const real_t* p ); void set( const real_t* evt ); - void set( const size_t& i, const real_t& p ) ; + void set( const unsigned& i, const real_t& p ) ; void swap( const unsigned int& i , const unsigned int& j ); - void setCache(const complex_t& value, const size_t& pos) ; - template void setCache( const std::array& value, const size_t& pos ) + void setCache(const complex_t& value, const unsigned& pos) ; + template void setCache( const std::array& value, const unsigned& pos ) { std::memmove( m_cache.data() + pos, value.data(), sizeof(std::array) ); } - void setCache( const std::vector& value, const size_t& pos ); + void setCache( const std::vector& value, const unsigned& pos ); void resizeCache( const unsigned int& new_size ); - size_t size() const { return m_event.size(); } + unsigned size() const { return m_event.size(); } - real_t* pWeight() { return &(m_weight); } - real_t* pGenPdf() { return &m_genPdf; } - const real_t* address(const unsigned int ref=0 ) const { return &(m_event[ref]); } - real_t* address(const unsigned int& ref=0) { return &(m_event[ref]); } + real_t* pWeight() { return &(m_weight); } + real_t* pGenPdf() { return &m_genPdf; } + const real_t* address(const unsigned& ref=0) const { return &(m_event[ref]); } + real_t* address(const unsigned& ref=0) { return &(m_event[ref]); } - unsigned int cacheSize() const { return m_cache.size(); } - real_t weight() const { return m_weight; } - real_t genPdf() const { return m_genPdf; } - real_t operator[](const unsigned int& i) const { return m_event[i]; } - real_t& operator[](const unsigned int& i) { return m_event[i]; } - operator const real_t*() const { return &(m_event[0]); } - operator real_t*() { return &(m_event[0]); } + unsigned cacheSize() const { return m_cache.size(); } + real_t weight() const { return m_weight; } + real_t genPdf() const { return m_genPdf; } + real_t operator[](const unsigned& i) const { return m_event[i]; } + real_t& operator[](const unsigned& i) { return m_event[i]; } + operator const real_t*() const { return &(m_event[0]); } + operator real_t*() { return &(m_event[0]); } - const complex_t& getCache(const unsigned int& pos) const { return m_cache[pos]; } - const complex_t* getCachePtr(const unsigned int& pos=0) const { return &(m_cache[0]) + pos; } + const complex_t& getCache(const unsigned& pos) const { return m_cache[pos]; } + const complex_t* getCachePtr(const unsigned& pos=0) const { return &(m_cache[0]) + pos; } void setWeight( const real_t& weight ){ m_weight = weight ; } void setGenPdf( const real_t& genPdf ){ m_genPdf = genPdf ; } @@ -59,17 +59,17 @@ namespace AmpGen { void print() const; void printCache() const; - real_t s( const size_t& index) const ; - real_t s( const size_t& index1, const size_t& index2 ) const ; - real_t s( const size_t& index1, const size_t& index2, const size_t& index3 ) const; - real_t s( const std::vector& indices ) const ; + real_t s( const unsigned& index) const ; + real_t s( const unsigned& index1, const unsigned& index2 ) const ; + real_t s( const unsigned& index1, const unsigned& index2, const unsigned& index3 ) const; + real_t s( const std::vector& indices ) const ; private: std::vector m_event; std::vector m_cache; real_t m_genPdf = {1}; real_t m_weight = {1}; - inline real_t get(const size_t& index ) const { return m_event[index]; }; + inline real_t get(const unsigned& index ) const { return m_event[index]; }; }; } diff --git a/AmpGen/EventType.h b/AmpGen/EventType.h index fe9f41e445f..d1f2168a684 100644 --- a/AmpGen/EventType.h +++ b/AmpGen/EventType.h @@ -31,27 +31,27 @@ namespace AmpGen EventType conj( const bool& headOnly = 0, const bool& dontConjHead = 0 ) const; /// Returns the event format, that matches between expressions and the names used in Particle. - std::map getEventFormat( const bool& outputNames = false ) const; + std::map getEventFormat( const bool& outputNames = false ) const; /// Counts the number of particles in this event type with /// the same name as the index'th name. - std::pair count(const size_t& index) const; - std::pair minmax( const std::vector& indices, bool isGeV = false ) const; + std::pair count(const unsigned& index) const; + std::pair minmax( const std::vector& indices, bool isGeV = false ) const; std::vector masses() const; std::string mother() const; - double mass( const size_t& index ) const; + double mass( const unsigned& index ) const; double motherMass() const; std::vector finalStates() const; bool isTimeDependent() const; - size_t eventSize() const; - size_t size() const; - size_t dof() const; - std::string operator[]( const size_t& index ) const; + unsigned eventSize() const; + unsigned size() const; + unsigned dof() const; + std::string operator[]( const unsigned& index ) const; std::string decayDescriptor() const; - std::string label( const size_t& index, bool isRoot = true ) const; - std::string label( const std::vector& index, bool isRoot = true ) const; - std::vector defaultProjections(const size_t& nBins) const; - Projection projection(const size_t& nBins, const std::vector& indices, const std::string& observable = "mass2") const; + std::string label( const unsigned& index, bool isRoot = true ) const; + std::string label( const std::vector& index, bool isRoot = true ) const; + std::vector defaultProjections(const unsigned& nBins) const; + Projection projection(const unsigned& nBins, const std::vector& indices, const std::string& observable = "mass2") const; bool operator==( const EventType& other ) const; bool has( const std::string& name ) const; @@ -62,7 +62,7 @@ namespace AmpGen std::function symmetriser() const; /// Calculates the number of spin indices associated with the initial and final state, i.e. the rank of the relevant transition matrix. - std::pair dim() const; + std::pair dim() const; private: std::string m_mother; ///< name of decaying particle @@ -72,7 +72,7 @@ namespace AmpGen std::vector m_particleMasses; ///< masses of decay products bool m_timeDependent; ///< Flag to include a decay time as the last element in the event vector std::vector m_eventTypeExtensions; ///< extended event data - std::pair m_dim; ///< Rank of the relevant transition matrix + std::pair m_dim; ///< Rank of the relevant transition matrix bool m_alt_part_names; ///< alternative naming in ouput tree (e.g. Xi- pi+ pi+ becomes Xim pip0 pip1 rather than _1_Xi# _2_pi~ _3_pi~) }; std::ostream& operator<<( std::ostream& os, const EventType& type ); diff --git a/AmpGen/ExpressionParser.h b/AmpGen/ExpressionParser.h index 73e379debd2..7932bcc94e0 100644 --- a/AmpGen/ExpressionParser.h +++ b/AmpGen/ExpressionParser.h @@ -18,7 +18,7 @@ namespace AmpGen class MinuitParameterLink : public IExpression { public: - MinuitParameterLink( MinuitParameter* param ) ; + explicit MinuitParameterLink( MinuitParameter* param ) ; std::string to_string(const ASTResolver* resolver=nullptr) const override ; void resolve( ASTResolver& resolver ) const override ; complex_t operator()() const override ; @@ -31,7 +31,7 @@ namespace AmpGen class ExpressionPack : public IExpression { public: - ExpressionPack( const std::vector& expressions ){ m_expressions = expressions ; } + explicit ExpressionPack( const std::vector& expressions ): m_expressions(expressions) {} ExpressionPack( const Expression& A, const Expression& B ); std::string to_string(const ASTResolver* resolver=nullptr) const override; void resolve( ASTResolver& resolver ) const override; diff --git a/AmpGen/FastDT.h b/AmpGen/FastDT.h index 37158765c53..14f2953e4ae 100644 --- a/AmpGen/FastDT.h +++ b/AmpGen/FastDT.h @@ -24,14 +24,14 @@ namespace AmpGen { { public: struct Node { - unsigned int index; - int left; - int right; - double cutValue; + unsigned index; + unsigned left; + unsigned right; + double cutValue; Node(){}; - Node(const unsigned int& index, - const int& left, - const int& right, + Node(const unsigned& index, + const unsigned& left, + const unsigned& right, const double& cutValue) : index(index), left(left), right(right), cutValue(cutValue) {}; }; FastDT() = default; @@ -41,8 +41,8 @@ namespace AmpGen { std::vector m_nodes; std::function(const Event&)> m_functors; std::queue m_queueOrdering; - size_t m_dim; - size_t m_minEvents; + size_t m_dim = {0}; + size_t m_minEvents = {0}; size_t m_maxDepth = {0}; int m_endNodeCounter = {0}; int makeNodes(std::vector& evts, std::queue indexQueue, const size_t& depth); diff --git a/AmpGen/FitResult.h b/AmpGen/FitResult.h index ed39584dbc6..88cac144df5 100644 --- a/AmpGen/FitResult.h +++ b/AmpGen/FitResult.h @@ -16,9 +16,9 @@ namespace AmpGen { public: FitResult(); - FitResult( const FitResult& other ); - FitResult( const std::string& filename ); - FitResult( const Minimiser& mini ); + explicit FitResult( const FitResult& other ); + explicit FitResult( const std::string& filename ); + explicit FitResult( const Minimiser& mini ); FitResult( const MinuitParameterSet& mps, const TMatrixD& covMini ); void addObservable( const std::string& name, const double& F ); diff --git a/AmpGen/Generator.h b/AmpGen/Generator.h index 8b258e044be..87e1243775e 100644 --- a/AmpGen/Generator.h +++ b/AmpGen/Generator.h @@ -21,7 +21,7 @@ namespace AmpGen public: template - Generator( const ARGS&... args ) + explicit Generator( const ARGS&... args ) : m_gps(args...) { m_eventType = m_gps.eventType(); @@ -139,7 +139,7 @@ namespace AmpGen void prepare(){}; void setEvents( AmpGen::EventList& /*evts*/ ){}; double prob_unnormalised( const AmpGen::Event& evt ) const { return m_fcn(evt); } - PDFWrapper( const FCN& fcn ) : m_fcn(fcn) {} + explicit PDFWrapper( const FCN& fcn ) : m_fcn(fcn) {} size_t size() const { return 0; } void reset( const bool& /*flag*/ = false ){}; diff --git a/AmpGen/Kinematics.h b/AmpGen/Kinematics.h index 6385fe8230e..a86ebb8e6e4 100644 --- a/AmpGen/Kinematics.h +++ b/AmpGen/Kinematics.h @@ -23,15 +23,15 @@ namespace AmpGen */ class HelicityCosine { public: - HelicityCosine(const std::vector& p1, const std::vector& p2, - const std::vector& pR); + HelicityCosine(const std::vector& p1, const std::vector& p2, + const std::vector& pR); - HelicityCosine(const size_t& i, const size_t& j, const std::vector& pR); + HelicityCosine(const unsigned& i, const unsigned& j, const std::vector& pR); double operator()( std::vector::iterator evt ) const; double operator()( const Event& evt ) const; private: - std::vector _i, _j, _pR; + std::vector _i, _j, _pR; }; /** @ingroup Kin class MomentumTransfer @@ -39,13 +39,13 @@ namespace AmpGen */ class MomentumTransfer { public: - MomentumTransfer( const std::vector& _p1, const std::vector& _p2 ); + MomentumTransfer( const std::vector& _p1, const std::vector& _p2 ); double operator()( const Event& evt ) const; private: double Q2( const double& s, const double& s1, const double& s2 ) const; - std::vector p1; - std::vector p2; - std::vector s; + std::vector p1; + std::vector p2; + std::vector s; }; /** @ingroup Kin function acoplanarity @@ -79,12 +79,12 @@ namespace AmpGen /** @ingroup Kin function pFromEvent @brief Helper function to extract a TLorentzVector of the ith decay product from an AmpGen::Event. */ - TLorentzVector pFromEvent( const Event& evt, const size_t& ref ); + TLorentzVector pFromEvent( const Event& evt, const unsigned& ref ); /** @ingroup Kin function pFromEvent @brief Helper function to extract a TLorentzVector of the sum of {2} decay product from an AmpGen::Event. */ - TLorentzVector pFromEvent( const Event& evt, const std::vector& ref ); + TLorentzVector pFromEvent( const Event& evt, const std::vector& ref ); } // namespace AmpGen #endif diff --git a/AmpGen/Lineshapes.h b/AmpGen/Lineshapes.h index 4ba61cc69fa..9c36c384e74 100644 --- a/AmpGen/Lineshapes.h +++ b/AmpGen/Lineshapes.h @@ -60,7 +60,7 @@ const std::string& lineshapeModifier, \ AmpGen::DebugSymbols* dbexpressions ) const { return \ get(p.massSq(), p.daughter(0)->massSq(), p.daughter(1)->massSq(), \ - p.name(), p.orbital(), lineshapeModifier, dbexpressions) ;} \ + p.name(), p.L(), lineshapeModifier, dbexpressions) ;} \ AmpGen::Expression Lineshape::X::get( const AmpGen::Expression& s, const AmpGen::Expression& s1, \ const AmpGen::Expression& s2, const std::string& particleName, \ const unsigned int& L, const std::string& lineshapeModifier, \ @@ -90,7 +90,7 @@ namespace AmpGen public: virtual ~Base() = default; virtual Expression get( const Expression& s, const Expression& s1, const Expression& s2, - const std::string& particleName, const unsigned int& L, + const std::string& particleName, const unsigned& L, const std::string& lineshapeModifier, DebugSymbols* dbexpressions = nullptr ) const = 0; virtual Expression get( const AmpGen::Particle& p, const std::string& lineshapeModifier, @@ -102,7 +102,7 @@ namespace AmpGen { public: static Expression get(const std::string& lineshape, const Expression& s, const Expression& s1, - const Expression& s2, const std::string& particleName, const unsigned int& L, + const Expression& s2, const std::string& particleName, const unsigned& L, std::vector>* dbexpressions = nullptr ); static Expression get(const std::string& lineshape, const Particle& p, diff --git a/AmpGen/MetaUtils.h b/AmpGen/MetaUtils.h index 4a74f1c089f..20b6ac06253 100644 --- a/AmpGen/MetaUtils.h +++ b/AmpGen/MetaUtils.h @@ -9,7 +9,7 @@ namespace AmpGen { - /** Utility classes for (library) compile-level metaprogramming, such as identifying the types of + /** Utility classes for compile-time metaprogramming, such as identifying the types of arguments for generating source code, compile-time unrolling of tuples and loops, and identifying if a class can be constructed in different ways. */ @@ -55,12 +55,6 @@ namespace AmpGen for_each( t, f ); } - - template std::shared_ptr makeShared( const TYPE& obj ) - { - return std::make_shared( obj ); - } - template () != "void" ) { rt.emplace_back( typeof() ); auto rtp = typelist(); - for( auto& r : rtp ) rt.emplace_back( r ); + std::copy( rtp.begin(), rtp.end(), std::back_inserter(rt) ); } return rt; } diff --git a/AmpGen/MsgService.h b/AmpGen/MsgService.h index 775f4d297e6..a8d8c873585 100644 --- a/AmpGen/MsgService.h +++ b/AmpGen/MsgService.h @@ -40,7 +40,6 @@ inline std::string trimmedString( std::string thing, const unsigned int& length return pos < length ? thing.substr( 0, pos ) : thing.substr( 0, length ); } return thing.size() < length ? thing : thing.substr( 0, length ) + "..."; - if ( thing.size() < length ) return thing; } /// @ingroup msgService macro DEBUG diff --git a/AmpGen/NamedParameter.h b/AmpGen/NamedParameter.h index bbaa6056b12..a654e65cee0 100644 --- a/AmpGen/NamedParameter.h +++ b/AmpGen/NamedParameter.h @@ -76,7 +76,6 @@ namespace AmpGen } void help(const T& def){ - std::map< std::string, std::string > aliases; std::string type = typeof(); if( type == "std::__cxx11::basic_string, std::allocator >" ) type = "string"; std::cout << " " << bold_on << std::left << std::setw(27) << m_name << bold_off diff --git a/AmpGen/Particle.h b/AmpGen/Particle.h index b3f9a9a9db1..7c53cfbce9d 100644 --- a/AmpGen/Particle.h +++ b/AmpGen/Particle.h @@ -176,7 +176,8 @@ namespace AmpGen double mass() const; ///< Returns the (PDG) mass of the particle double spin() const; ///< Returns the spin of the particle - double S() const; + double S() const; ///< Returns the spin configuration of the decay products of the particle + unsigned L() const; ///< Returns the orbital angular bool isHead() const; ///< Returns whether if this particle is the head of the decay, i.e. has no parent bool isWeakDecay() const; ///< Returns whether is this particle decays weakly or not @@ -185,9 +186,8 @@ namespace AmpGen bool isQuasiStable() const; ///< Check whether the particle is quasi-stable, i.e. may have some appreciable flight distance bool conservesParity( unsigned int L = 0 ) const; ///< Check whether the decay of this particle with angular momentum L conserves parity or not - unsigned int orbital() const; ///< Returns the orbital angular - unsigned int index() const; ///< Returns the current index of the particle in event data structure. Can differ from the original index due to symmetrisation - unsigned int originalIndex() const; ///< Returns the original index of the particle + unsigned index() const; ///< Returns the current index of the particle in event data structure. Can differ from the original index due to symmetrisation + unsigned originalIndex() const; ///< Returns the original index of the particle std::string name() const; ///< Name of the decaying particle. std::string lineshape() const; ///< Name of the propagator to use for the decay of this particle. std::string vertexName() const; ///< Name of the (spin)vertex to use for the decay of this particle @@ -268,17 +268,17 @@ namespace AmpGen unsigned int matches( const Particle& other ) const; private: - const ParticleProperties* m_props; ///< Particle Properties from the PDG + const ParticleProperties* m_props = {nullptr}; ///< Particle Properties from the PDG std::string m_name = {""}; ///< Name of the particle std::string m_lineshape = {"BW"}; ///< Propagator to use std::string m_uniqueString = {""}; ///< Unique string of particle tree int m_parity = {0}; ///< Intrinsic parity of particle - int m_polState = {0}; ///< polarisation state - unsigned int m_index = {999}; ///< Index, for constructing four-momenta - unsigned int m_originalIndex = {999}; ///< Starting index, used in Bose-symmetrisation - unsigned int m_orbital = {0}; ///< Orbital angular momentum between daughters - unsigned int m_spinConfigurationNumber = {0}; ///< Spin configuration quantum number 'S' - unsigned int m_minL = {0}; ///< Minimum orbital angular momentum + int m_polState = {0}; ///< Projection of the spin along the quantisation axis, i.e. 'z' + unsigned m_index = {999}; ///< Index, for constructing four-momenta + unsigned m_originalIndex = {999}; ///< Starting index, used in Bose-symmetrisation + unsigned m_orbital = {0}; ///< Orbital angular momentum between daughters + unsigned m_spinConfigurationNumber = {0}; ///< Spin configuration quantum number 'S' + unsigned m_minL = {0}; ///< Minimum orbital angular momentum bool m_isHead = {true}; ///< Flag that particle is head of decay chain bool m_usesDefaultLineshape = {false}; ///< Flag to check if default shape is used bool m_isStateGood = {true}; ///< Flag to check the decay is well-formed diff --git a/AmpGen/ParticleProperties.h b/AmpGen/ParticleProperties.h index 97cc3c7a4d4..d68ac653334 100644 --- a/AmpGen/ParticleProperties.h +++ b/AmpGen/ParticleProperties.h @@ -26,7 +26,7 @@ namespace AmpGen class ParticleProperties { public: - ParticleProperties( const std::string& pdg_string = "" ); ///< Constructor from a string formatted by the PDG convention. + explicit ParticleProperties( const std::string& pdg_string = "" ); ///< Constructor from a string formatted by the PDG convention. double mass() const { return m_mass * MeV; } ///< Returns mass of particle in MeV double mErrPlus() const { return m_mErrPlus * MeV; } ///< Returns +ve uncertainty on particle mass in MeV double mErrMinus() const { return m_mErrMinus * MeV; } ///< Returns -ve uncertainty on particle mass in MeV diff --git a/AmpGen/ParticlePropertiesList.h b/AmpGen/ParticlePropertiesList.h index 0256ff3ca4d..43806094b46 100644 --- a/AmpGen/ParticlePropertiesList.h +++ b/AmpGen/ParticlePropertiesList.h @@ -24,7 +24,7 @@ namespace AmpGen std::map m_byID; double m_quasiStableThreshold; - ParticlePropertiesList( const std::string& fname_in = "mass_width.csv" ); + explicit ParticlePropertiesList( const std::string& fname_in = "mass_width.csv" ); protected: const std::vector dirList() const; diff --git a/AmpGen/Projection.h b/AmpGen/Projection.h index 393139cfd35..ea0f02378ec 100644 --- a/AmpGen/Projection.h +++ b/AmpGen/Projection.h @@ -24,9 +24,9 @@ namespace AmpGen public: Projection(); template - Projection( const FCN& fcn, const std::string& name, - const std::string& xAxisTitle, const size_t& nBins, const double& min, const double& max, - const std::string& units = "" ) : Projection( std::function< double( const Event& )>( fcn ), name, xAxisTitle, nBins, min, max, units ) {} + Projection( const FCN& fcn, const std::string& name, + const std::string& xAxisTitle, const size_t& nBins, const double& min, const double& max, + const std::string& units = "" ) : Projection( std::function< double( const Event& )>( fcn ), name, xAxisTitle, nBins, min, max, units ) {} Projection( const std::function& fcn, const std::string& name, const std::string& xAxisTitle, const size_t& nBins, const double& min, const double& max, const std::string& units = "" ); @@ -41,13 +41,13 @@ namespace AmpGen friend class Projection2D; private: std::function m_func; - std::string m_name; - std::string m_xAxisTitle; - std::string m_units; - size_t m_nBins; - double m_min; - double m_max; - double m_width; + std::string m_name = {""}; + std::string m_xAxisTitle = {""}; + std::string m_units = {""}; + size_t m_nBins = {0}; + double m_min = {0}; + double m_max = {0}; + double m_width = {0}; }; class Projection2D diff --git a/AmpGen/QuarkContent.h b/AmpGen/QuarkContent.h index 7b291ce32e9..061750ba6df 100644 --- a/AmpGen/QuarkContent.h +++ b/AmpGen/QuarkContent.h @@ -17,9 +17,8 @@ namespace AmpGen std::array m_quarks; public: QuarkState(); - QuarkState( const std::string& str ); + explicit QuarkState( const std::string& str ); void antiThis(); - void initFromString( const std::string& str ); char nameFromPosition( int i ) const; int positionFromName( char c ) const; bool isVacuum() const; @@ -39,9 +38,8 @@ namespace AmpGen std::vector m_quarks; public: QuarkContent(); - QuarkContent( const std::string& str ){ initFromString(str); } + explicit QuarkContent( const std::string& str ); void antiThis(); - void initFromString( const std::string& str ); void print( std::ostream& os = std::cout ) const; size_t size() const; bool compatible( const QuarkContent& other ) const; diff --git a/AmpGen/RecursivePhaseSpace.h b/AmpGen/RecursivePhaseSpace.h index 073a21ae7d7..0d63cfa3190 100644 --- a/AmpGen/RecursivePhaseSpace.h +++ b/AmpGen/RecursivePhaseSpace.h @@ -21,35 +21,42 @@ namespace AmpGen { class Particle; class Event; - + /** @class RecursivePhaseSpace + @brief Generator of events with more complex topologies. + @decription Generates events in the phase space of a decay with one-or-more quasistable products + that are further decayed, where these quasistable products are suitably long-lived + that their propagators can be assumed to be delta-functions, i.e. particles such as + @f$ \Lambda^0 , {K_\rm{S}}^0 @f$ etc. Such a process has a natural factorisation into + each of these steps. For each of the decays of a quasistable particle, the PhaseSpace + generator is used, which is itself based heavily on TGenPhaseSpace. + */ class RecursivePhaseSpace { private: struct Node { - std::string name; - int sink = {-1}; + std::string name = {""}; + int sink = {-1}; std::shared_ptr decayProds = {nullptr}; - Node( const std::string& _name ) : name( _name ) {}; + explicit Node( const std::string& _name ) : name( _name ) {}; }; public: - RecursivePhaseSpace(const EventType& type); + explicit RecursivePhaseSpace(const EventType& type); RecursivePhaseSpace(const Particle& decayChain, const EventType& type, TRandom* rndm = gRandom); std::vector getFinalStates(); void print( const size_t& offset = 0 ) const; void setRandom( TRandom* rand ); - AmpGen::Event makeEvent( const size_t& cacheSize = 0 ); + Event makeEvent( const size_t& cacheSize = 0 ); size_t size() const; EventType eventType() const ; private: PhaseSpace m_phsp; - unsigned int m_totalSize; - std::string m_name; + unsigned m_totalSize = {0}; + std::string m_name = {""}; EventType m_eventType; std::vector m_nodes; - }; } // namespace AmpGen diff --git a/AmpGen/SumPDF.h b/AmpGen/SumPDF.h index ed182afffba..dbce73fcdff 100644 --- a/AmpGen/SumPDF.h +++ b/AmpGen/SumPDF.h @@ -39,7 +39,7 @@ namespace AmpGen private: typedef typename eventListType::value_type eventValueType; ///< The value type stored in the eventListType std::tuple m_pdfs; ///< The tuple of probability density functions - eventListType* m_events; ///< The event list to evaluate likelihoods on + eventListType* m_events = {nullptr}; ///< The event list to evaluate likelihoods on public: /// Default Constructor diff --git a/AmpGen/Tensor.h b/AmpGen/Tensor.h index 41ca85ac905..168970d485b 100644 --- a/AmpGen/Tensor.h +++ b/AmpGen/Tensor.h @@ -15,11 +15,11 @@ #include "AmpGen/Types.h" #define ADD_DEBUG_TENSOR( X, Y ) \ - if ( Y != nullptr ) for( size_t i = 0 ; i < X.size(); ++i ) \ + if ( Y != nullptr ) for( unsigned i = 0 ; i < X.size(); ++i ) \ Y->emplace_back( std::string(#X) + Tensor::coordinates_to_string( X.coords(i) ) , X[i] ); #define ADD_DEBUG_TENSOR_NAMED( X, Y, Z ) \ - if ( Y != nullptr ) for( size_t i = 0 ; i < X.size(); ++i ) \ + if ( Y != nullptr ) for( unsigned i = 0 ; i < X.size(); ++i ) \ Y->emplace_back( Z + Tensor::coordinates_to_string( X.coords(i) ) , X[i] ); namespace AmpGen @@ -34,52 +34,51 @@ namespace AmpGen private: std::shared_ptr m_ptr; bool m_isUpper; - std::string name; public: bool operator==( const Tensor::Index& other ) const { return m_ptr.get() == other.m_ptr.get(); } bool operator!=( const Tensor::Index& other ) const { return m_ptr.get() != other.m_ptr.get(); } bool isUpper() const { return m_isUpper; }; - Index( bool isUpper = false ) : m_ptr( new int() ), m_isUpper( isUpper ) {} + explicit Index( bool isUpper = false ) : m_ptr( new int() ), m_isUpper( isUpper ) {} Index( const std::shared_ptr& index, bool isUpper = false ) : m_ptr( index ), m_isUpper( isUpper ) {} Index operator-() const { return Index( m_ptr, !m_isUpper ); } friend std::ostream& operator <<( std::ostream& out, const Index& index ); }; Tensor(); - Tensor(const std::vector& elements); - Tensor(const std::vector& dim); + explicit Tensor(const std::vector& elements); + explicit Tensor(const std::vector& dim); template Tensor(const std::initializer_list& elements, - const std::vector& dim) : m_dim(dim) + const std::vector& dim) : m_dim(dim) { setupCoordinates(); for ( auto& x : elements ) append( x ); } template Tensor(const std::vector& elements, - const std::vector& dim) : m_dim(dim) + const std::vector& dim) : m_dim(dim) { setupCoordinates(); for ( auto& x : elements ) append( x ); } /// Low level access of elements, either by coordinates or by index /// - Expression& operator[]( const size_t& i ); - Expression& operator[]( const std::vector& co ); - const Expression& operator[]( const size_t& i ) const; - const Expression& operator[]( const std::vector& co ) const; + Expression& operator[]( const unsigned& i ); + Expression& operator[]( const std::vector& co ); + const Expression& operator[]( const unsigned& i ) const; + const Expression& operator[]( const std::vector& co ) const; - Expression get( const size_t& co ); - Expression get( const size_t& co ) const; - Expression get( const std::vector& _co ) const; + Expression get( const unsigned& co ); + Expression get( const unsigned& co ) const; + Expression get( const std::vector& _co ) const; /// TensorProxy access to class members /// High level access is done via these commands, i.e. () operators - Expression& operator()( const size_t& a ) { return Tensor::operator[]( {a} ) ; } - Expression& operator()( const size_t& a, const size_t& b) { return Tensor::operator[]( {a,b} ) ; } - const Expression operator()( const size_t& a ) const { return Tensor::operator[]( {a} ) ; } - const Expression& operator()( const size_t& a, const size_t& b) const { return Tensor::operator[]( {a,b} ) ; } + Expression& operator()( const unsigned& a ) { return Tensor::operator[]( {a} ) ; } + Expression& operator()( const unsigned& a, const unsigned& b) { return Tensor::operator[]( {a,b} ) ; } + const Expression operator()( const unsigned& a ) const { return Tensor::operator[]( {a} ) ; } + const Expression& operator()( const unsigned& a, const unsigned& b) const { return Tensor::operator[]( {a,b} ) ; } TensorProxy operator()( const Tensor::Index& a ) const; TensorProxy operator()( const Tensor::Index& a, const Tensor::Index& b ) const; @@ -93,52 +92,52 @@ namespace AmpGen void st(const bool simplify=false); bool rankMatches( const Tensor& other ); - void imposeSymmetry( size_t indexA, size_t indexB); - void imposeSymmetry( std::vector indices ); + void imposeSymmetry( unsigned indexA, unsigned indexB); + void imposeSymmetry( std::vector indices ); Tensor Invert() const; std::string to_string(const ASTResolver* resolver=nullptr) const ; - int metricSgn( const std::vector& coordinates ) const; - int metricSgn( const size_t& index ) const; + int metricSgn( const std::vector& coordinates ) const; + int metricSgn( const unsigned& index ) const; void append( const Expression& expression ); void append( const real_t& value ); void append( const complex_t& value ); void append( const std::string& value ); void setupCoordinates(); - size_t nDim() const; - size_t rank() const; - size_t size() const; - size_t index( const std::vector& _co ) const; - size_t symmetrisedIndex( const std::vector& _co ) const; - size_t nElements() const; + unsigned nDim() const; + unsigned rank() const; + unsigned size() const; + unsigned index( const std::vector& _co ) const; + unsigned symmetrisedIndex( const std::vector& _co ) const; + unsigned nElements() const; - const std::vector coords( const size_t& index ) const; - const std::vector& dims() const { return m_dim; } + const std::vector coords( const unsigned& index ) const; + const std::vector& dims() const { return m_dim; } const std::string dimString() const ; void print(const bool& eval = false) const; - const std::vector& uniqueElements() const { return m_uniqueElements; } + const std::vector& uniqueElements() const { return m_uniqueElements; } void operator+=( const Tensor& rhs ); void operator-=( const Tensor& rhs ); Tensor conjugate() const; - static std::vector index_to_coordinates( const size_t& index, const std::vector& dim ); - static size_t coordinates_to_index( const std::vector& coords, const std::vector& dim ); - static std::string coordinates_to_string( const std::vector& coordinates ); + static std::vector index_to_coordinates( const unsigned& index, const std::vector& dim ); + static unsigned coordinates_to_index( const std::vector& coords, const std::vector& dim ); + static std::string coordinates_to_string( const std::vector& coordinates ); template - static std::vector dim( const ARGS&... args ){ - std::vector rt; + static std::vector dim( const ARGS&... args ){ + std::vector rt; auto up = std::tuple(args...); - for_each(up, [&rt]( const size_t& f ) { rt.emplace_back(f); } ); + for_each(up, [&rt]( const unsigned& f ) { rt.emplace_back(f); } ); return rt; } private: - std::vector m_dim; - std::vector m_symmetrisedCoordinates; - std::vector m_uniqueElements; + std::vector m_dim; + std::vector m_symmetrisedCoordinates; + std::vector m_uniqueElements; std::vector m_elements; }; @@ -200,9 +199,9 @@ namespace AmpGen TensorProxy operator*(const double& , const TensorProxy&); TensorProxy operator*(const TensorProxy&, const double&); - Tensor Identity( const size_t& rank = 4 ); + Tensor Identity( const unsigned& rank = 4 ); - const Tensor LeviCivita( const size_t& rank = 4); + const Tensor LeviCivita( const unsigned& rank = 4); Expression dot( const Tensor& A, const Tensor& B ); std::ostream& operator <<( std::ostream& out, const Tensor::Index& index ); diff --git a/AmpGen/ThreadPool.h b/AmpGen/ThreadPool.h index d00031f4a1c..589a06e1422 100644 --- a/AmpGen/ThreadPool.h +++ b/AmpGen/ThreadPool.h @@ -3,7 +3,8 @@ /* @class ThreadPool ThreadPool.h AmpGen/ThreadPool.h * Thread pool implementation taken from https://github.com/progschj/ThreadPool - * Modified to allow explicit clearing of queues. + * Modified to allow explicit clearing of queues, and to make + * the constructor explicit * * Copyright (c) 2012 Jakob Progsch, Václav Zeman * @@ -47,7 +48,7 @@ namespace AmpGen class ThreadPool { public: - ThreadPool(const size_t& nt); + explicit ThreadPool(const size_t& nt); ~ThreadPool(); template auto enqueue(F&& f, Args&&... args) -> std::future::type>; void waitForStoppedThreads(); diff --git a/AmpGen/Utilities.h b/AmpGen/Utilities.h index 98cc1e0f2e1..63d063fafc4 100644 --- a/AmpGen/Utilities.h +++ b/AmpGen/Utilities.h @@ -19,22 +19,6 @@ #include "AmpGen/MsgService.h" #include "AmpGen/MetaUtils.h" namespace AmpGen { - template - bool isIn( const std::vector& container, const T& obj ) - { - for ( auto& it : container ) - if ( obj == it ) return true; - return false; - } - - template - bool isIn( const std::vector& container, const B& obj, F f ) - { - for ( auto& it : container ) - if ( f( it, obj ) ) return true; - return false; - } - template std::string vectorToString( const std::vector& obj, const std::string& delim = "" ) { @@ -200,7 +184,7 @@ namespace AmpGen { std::string ltrim( std::string s ); std::string rtrim( std::string s ); - std::string trim( std::string s ); + std::string trim( const std::string& s ); std::string expandGlobals( std::string path ); std::ostream& bold_on( std::ostream& ); diff --git a/AmpGen/Wigner.h b/AmpGen/Wigner.h index cd6c4a7aec5..9abdcf1f372 100644 --- a/AmpGen/Wigner.h +++ b/AmpGen/Wigner.h @@ -34,12 +34,12 @@ namespace AmpGen { Tensor basisVector(const int& polState); struct LS { - double factor; - double cg1; - double cg2; - double p; - double m1; - double m2; + double factor = {1}; + double cg1 = {0}; + double cg2 = {0}; + double p = {0}; + double m1 = {0}; + double m2 = {0}; }; std::vector calculate_recoupling_constants( diff --git a/AmpGen/kMatrix.h b/AmpGen/kMatrix.h index 18f07095eb0..c7cbcb1ce9b 100644 --- a/AmpGen/kMatrix.h +++ b/AmpGen/kMatrix.h @@ -37,11 +37,11 @@ namespace AmpGen couplings.push_back( coupling ); bl_factors.push_back( bl_factor ); } - const Expression coupling(const size_t& i) const { return couplings[i] * bl_factors[i]; } - const Expression g(const size_t& i) const { return couplings[i]; } + const Expression coupling(const unsigned& i) const { return couplings[i] * bl_factors[i]; } + const Expression g(const unsigned& i) const { return couplings[i]; } }; - Tensor constructKMatrix(const Expression& s, const size_t& nChannels, + Tensor constructKMatrix(const Expression& s, const unsigned& nChannels, const std::vector& poleConfigs); Expression phsp_twoBody( const Expression& s, const double& m0, const double& m1 ); diff --git a/apps/Generator.cpp b/apps/Generator.cpp index 26751a0da1d..07137d0defb 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -33,7 +33,7 @@ using namespace AmpGen; namespace AmpGen { make_enum(generatorType, CoherentSum, PolarisedSum, FixedLib, RGenerator) } struct FixedLibPDF { - void* lib; + void* lib = {nullptr}; AmpGen::DynamicFCN PDF; void prepare(){}; @@ -73,10 +73,10 @@ int main( int argc, char** argv ) int seed = NamedParameter ("Seed" , 0, "Random seed used in event Generation" ); std::string outfile = NamedParameter("Output" , "Generate_Output.root" , "Name of output file" ); auto genType = NamedParameter( "Type", generatorType::CoherentSum, optionalHelpString("Generator configuration to use:", - { {"CoherentSum", "Full phase-space generator with (pseudo)scalar amplitude"} + { {"CoherentSum" , "Full phase-space generator with (pseudo)scalar amplitude"} , {"PolarisedSum", "Full phase-space generator with particles carrying spin in the initial/final states"} - , {"FixedLib", "Full phase-space generator with an amplitude from a precompiled library"} - , {"RGenerator", "Recursive phase-space generator for intermediate (quasi)stable states such as the D-mesons"} } ) ); + , {"FixedLib" , "Full phase-space generator with an amplitude from a precompiled library"} + , {"RGenerator" , "Recursive phase-space generator for intermediate (quasi)stable states such as the D-mesons"} } ) ); std::string lib = NamedParameter("Library","","Name of library to use for a fixed library generation"); size_t nBins = NamedParameter ("nBins" ,100, "Number of bins for monitoring plots." ); diff --git a/examples/FitterWithPolarisation.cpp b/examples/FitterWithPolarisation.cpp index fd2340c85f9..129970e3acd 100644 --- a/examples/FitterWithPolarisation.cpp +++ b/examples/FitterWithPolarisation.cpp @@ -60,8 +60,6 @@ int main( int argc, char* argv[] ) if( dataFile == "" ) FATAL("Must specify input with option " << italic_on << "DataSample" << italic_off ); if( pNames.size() == 0 ) FATAL("Must specify event type with option " << italic_on << " EventType" << italic_off); - [[maybe_unused]] - size_t nThreads = NamedParameter ("nCores" , 8 , "Number of threads to use" ); size_t seed = NamedParameter ("Seed" , 0 , "Random seed used" ); TRandom3 rndm; @@ -71,6 +69,7 @@ int main( int argc, char* argv[] ) INFO("LogFile: " << logFile << "; Plots: " << plotFile ); #ifdef _OPENMP + size_t nThreads = NamedParameter ("nCores" , 8 , "Number of threads to use" ); omp_set_num_threads( nThreads ); INFO( "Setting " << nThreads << " fixed threads for OpenMP" ); omp_set_dynamic( 0 ); diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp index 653c32d5aff..5e6ec32f11b 100644 --- a/examples/QcGenerator.cpp +++ b/examples/QcGenerator.cpp @@ -323,9 +323,9 @@ void add_CP_conjugate( MinuitParameterSet& mps ) else { auto tokens=split(name,'_'); std::string reOrIm = *tokens.rbegin(); - std::string name = tokens[0]; + std::string pname = tokens[0]; if ( reOrIm == "Re" || reOrIm == "Im" ){ - auto p = Particle( name ).conj(); + auto p = Particle( pname ).conj(); sgn = reOrIm == "Re" ? p.quasiCP() : 1; new_name = p.uniqueString() +"_"+reOrIm; } diff --git a/examples/SignalOnlyFitter.cpp b/examples/SignalOnlyFitter.cpp index 0ca87852484..b3f1e0363e2 100644 --- a/examples/SignalOnlyFitter.cpp +++ b/examples/SignalOnlyFitter.cpp @@ -84,12 +84,15 @@ int main( int argc, char* argv[] ) /* An EventType specifies the initial and final state particles as a vector that will be described by the fit. It is typically loaded from the interface parameter EventType. */ EventType evtType(pNames); - /* A CoherentSum is the typical amplitude to be used, that is some sum over quasi two-body contributions weighted by an appropriate complex amplitude. The CoherentSum is generated from the couplings described by a set of parameters (in a MinuitParameterSet), and an EventType, which matches these parameters to a given final state and a set of data. A common set of rules can be matched to multiple final states, - i.e. to facilitate the analysis of coupled channels. */ + i.e. to facilitate the analysis of coupled channels. + The CoherentSum is only appropriate for decays involving only (pseudo)scalars in the inital / final state, + otherwise the sum must also be over initial / final spin states. In this case, as PolarisedSum should be used. + See FitterWithPolarisation for an example of this use case. + */ CoherentSum sig(evtType, MPS); /* Events are read in from ROOT files. If only the filename and the event type are specified, diff --git a/examples/modern.cpp b/examples/modern.cpp new file mode 100644 index 00000000000..e004ab8fa2e --- /dev/null +++ b/examples/modern.cpp @@ -0,0 +1,173 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "AmpGen/Chi2Estimator.h" +#include "AmpGen/EventList.h" +#include "AmpGen/EventType.h" +#include "AmpGen/CoherentSum.h" +#include "AmpGen/IncoherentSum.h" +#include "AmpGen/FitResult.h" +#include "AmpGen/Minimiser.h" +#include "AmpGen/MinuitParameterSet.h" +#include "AmpGen/MsgService.h" +#include "AmpGen/NamedParameter.h" +#include "AmpGen/SumPDF.h" +#include "AmpGen/Utilities.h" +#include "AmpGen/Generator.h" +#include "AmpGen/ErrorPropagator.h" +#include "AmpGen/functional/likelihood.h" +#ifdef _OPENMP + #include + #include +#endif + +#include +#include +#include + +using namespace AmpGen; + +template +FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& MPS ); + +int main( int argc, char* argv[] ) +{ + /* The user specified options must be loaded at the beginning of the programme, + and these can be specified either at the command line or in an options file. */ + OptionsParser::setArgs( argc, argv ); + + /* Parameters that have been parsed can be accessed anywhere in the program + using the NamedParameter class. The name of the parameter is the first option, + then the default value, and then the help string that will be printed if --h is specified + as an option. */ + std::string dataFile = NamedParameter("DataSample", "" , "Name of file containing data sample to fit." ); + std::string intFile = NamedParameter("IntegrationSample","" , "Name of file containing events to use for MC integration."); + std::string logFile = NamedParameter("LogFile" , "Fitter.log", "Name of the output log file"); + std::string plotFile = NamedParameter("Plots" , "plots.root", "Name of the output plot file"); + + auto bNames = NamedParameter("Branches", std::vector() + ,"List of branch names, assumed to be \033[3m daughter1_px ... daughter1_E, daughter2_px ... \033[0m" ).getVector(); + + auto pNames = NamedParameter("EventType" , "" + , "EventType to fit, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(); + + [[maybe_unused]] + size_t nThreads = NamedParameter ("nCores" , 8 , "Number of threads to use" ); + size_t seed = NamedParameter ("Seed" , 1 , "Random seed used" ); + + if( dataFile == "" ) FATAL("Must specify input with option " << italic_on << "DataSample" << italic_off ); + if( pNames.size() == 0 ) FATAL("Must specify event type with option " << italic_on << " EventType" << italic_off); + + TRandom3 rndm; + rndm.SetSeed( seed ); + gRandom = &rndm; + + INFO("LogFile: " << logFile << "; Plots: " << plotFile ); + +#ifdef _OPENMP + omp_set_num_threads( nThreads ); + INFO( "Setting " << nThreads << " fixed threads for OpenMP" ); + omp_set_dynamic( 0 ); +#endif + + /* A MinuitParameterSet is (unsurprisingly) a set of fit parameters, and can be loaded from + the parsed options. For historical reasons, this is referred to as loading it from a "Stream" */ + MinuitParameterSet MPS; + MPS.loadFromStream(); + + /* An EventType specifies the initial and final state particles as a vector that will be described by the fit. + It is typically loaded from the interface parameter EventType. */ + EventType evtType(pNames); + + /* A CoherentSum is the typical amplitude to be used, that is some sum over quasi two-body contributions + weighted by an appropriate complex amplitude. The CoherentSum is generated from the couplings described + by a set of parameters (in a MinuitParameterSet), and an EventType, which matches these parameters + to a given final state and a set of data. A common set of rules can be matched to multiple final states, + i.e. to facilitate the analysis of coupled channels. */ + CoherentSum sig(evtType, MPS); + + /* Events are read in from ROOT files. If only the filename and the event type are specified, + the file is assumed to be in the specific format that is defined by the event type, + unless the branches to load are specified in the user options */ + EventList events(dataFile, evtType, Branches(bNames), GetGenPdf(false) ); + + /* Generate events to normalise the PDF with. This can also be loaded from a file, + which will be the case when efficiency variations are included. Default number of normalisation events + is 5 million. */ + EventList eventsMC = intFile == "" ? Generator<>(evtType, &rndm).generate(2e6) : EventList(intFile, evtType, GetGenPdf(true)); + + sig.setMC( eventsMC ); + + TFile* output = TFile::Open( plotFile.c_str(), "RECREATE" ); output->cd(); + + /* Do the fit and return the fit results, which can be written to the log and contains the + covariance matrix, fit parameters, and other observables such as fit fractions */ + sig.setEvents( events ); + FitResult* fr = doFit( functional::make_likelihood(sig, events.begin(), events.end()), events, eventsMC, MPS ); + /* Calculate the `fit fractions` using the signal model and the error propagator (i.e. + fit results + covariance matrix) of the fit result, and write them to a file. + */ + auto fitFractions = sig.fitFractions( fr->getErrorPropagator() ); + + fr->addFractions( fitFractions ); + fr->writeToFile( logFile ); + output->cd(); + + /* Write out the data plots. This also shows the first example of the named arguments + to functions, emulating python's behaviour in this area */ + + auto plots = events.makeDefaultProjections(Prefix("Data"), Bins(100)); + for ( auto& plot : plots ) plot->Write(); + + output->Close(); +} + +template +FitResult* doFit( likelihoodType&& likelihood, EventList& data, EventList& mc, MinuitParameterSet& MPS ) +{ + auto time_wall = std::chrono::high_resolution_clock::now(); + auto time = std::clock(); + /* Minimiser is a general interface to Minuit1/Minuit2, + that is constructed from an object that defines an operator() that returns a double + (i.e. the likielihood, and a set of MinuitParameters. */ + Minimiser mini( likelihood, &MPS ); + mini.doFit(); + FitResult* fr = new FitResult(mini); + + auto twall_end = std::chrono::high_resolution_clock::now(); + double time_cpu = ( std::clock() - time ) / (double)CLOCKS_PER_SEC; + double tWall = std::chrono::duration( twall_end - time_wall ).count(); + INFO( "Wall time = " << tWall / 1000. ); + INFO( "CPU time = " << time_cpu ); + + /* Make the plots for the different components in the PDF, i.e. the signal and backgrounds. + The structure assumed the PDF is some SumPDF. */ + unsigned int counter = 1; + /* + for_each(likelihood.pdfs(), [&](auto& pdf){ + auto pfx = Prefix("Model_cat"+std::to_string(counter)); + auto mc_plot3 = mc.makeDefaultProjections(WeightFunction(pdf), pfx); + for( auto& plot : mc_plot3 ) + { + plot->Scale( ( data.integral() * pdf.getWeight() ) / plot->Integral() ); + plot->Write(); + } + counter++; + }); + */ + /* Estimate the chi2 using an adaptive / decision tree based binning, + down to a minimum bin population of 15, and add it to the output. */ +// Chi2Estimator chi2( data, mc, likelihood, 15 ); +// chi2.writeBinningToFile("chi2_binning.txt"); +// fr->addChi2( chi2.chi2(), chi2.nBins() ); + + fr->print(); + return fr; +} diff --git a/src/ASTResolver.cpp b/src/ASTResolver.cpp index 1faaf6f6ea1..8732bed9b14 100644 --- a/src/ASTResolver.cpp +++ b/src/ASTResolver.cpp @@ -12,7 +12,7 @@ using namespace AmpGen; -ASTResolver::ASTResolver(const std::map& evtMap, +ASTResolver::ASTResolver(const std::map& evtMap, const MinuitParameterSet* mps ) : m_evtMap(evtMap), m_mps(mps), diff --git a/src/BinDT.cpp b/src/BinDT.cpp index fe78d92e7be..911ab247989 100644 --- a/src/BinDT.cpp +++ b/src/BinDT.cpp @@ -15,7 +15,7 @@ using namespace AmpGen; -double nearestNeighbourVariance(std::vector evts, const size_t& index) +double nearestNeighbourVariance( std::vector evts, const size_t& index) { auto dist = [&index](const double* x, const double* y){ return fabs( *(x+index) -*(y+index)) ;}; auto dist2 = [&index](const double* x, const double* y){ return ( *(x+index) -*(y+index))*( *(x+index) - *(y+index) ) ;}; @@ -80,7 +80,7 @@ std::function( const Event& )> BinDT::makeDefaultFunctors() DEBUG( "Problem has 2 d.o.f.s -> using Dalitz coordinates" ); return []( const Event& evt ) -> std::vector { return {evt.s( 0, 1 ), evt.s( 1, 2 )}; }; } - DEBUG( "No functors found for dim = " << m_dim ); + ERROR( "No functors found for dim = " << m_dim ); return nullptr; } @@ -149,7 +149,7 @@ void BinDT::serialize( const std::string& filename ) output.close(); } -std::shared_ptr BinDT::makeNodes( std::vector evts ) +std::shared_ptr BinDT::makeNodes( const std::vector& evts ) { INFO( "Making nodes" ); std::queue iq; @@ -162,8 +162,7 @@ std::shared_ptr BinDT::makeNodes( std::vector evts ) return node; } -std::shared_ptr BinDT::makeNodes( std::vector evts, std::queue indexQueue, - const unsigned int& depth ) +std::shared_ptr BinDT::makeNodes( const std::vector& evts, std::queue indexQueue, const unsigned& depth ) { unsigned int index = indexQueue.front(); DEBUG( "Depth = " << depth << " nodes = " << m_endNodes.size() << " maxDepth = " << m_maxDepth @@ -184,7 +183,7 @@ std::shared_ptr BinDT::makeNodes( std::vector evts, std:: return node; } -std::shared_ptr BinDT::makeNodes( std::vector source, std::vector target ) +std::shared_ptr BinDT::makeNodes( const std::vector& source, const std::vector& target ) { std::queue iq; refreshQueue( source, iq, 0 ); diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index b4d0c255e17..3233a917806 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -14,21 +14,21 @@ #include "AmpGen/ProfileClock.h" using namespace AmpGen; +CompiledExpressionBase::CompiledExpressionBase() = default; + +CompiledExpressionBase::CompiledExpressionBase( const std::string& name ) : + m_name( name ), + m_progName( programatic_name(name) ) {} + CompiledExpressionBase::CompiledExpressionBase( const Expression& expression, const std::string& name, const DebugSymbols& db, - const std::map& evtMapping ) - : m_obj( expression ), + const std::map& evtMapping ) : + m_obj( expression ), m_name( name ), m_progName( programatic_name(name) ), m_db(db), - m_evtMap(evtMapping){} - -CompiledExpressionBase::CompiledExpressionBase( const std::string& name ) - : m_name( name ), - m_progName( programatic_name(name) ) {} - -CompiledExpressionBase::CompiledExpressionBase() = default; + m_evtMap(evtMapping) {} CompiledExpressionBase::~CompiledExpressionBase() {} diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index 66e503732e8..c6eceaa4c23 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -127,7 +127,7 @@ void CompilerWrapper::compileSource( const std::string& fname, const std::string "-shared", "-rdynamic", "-fPIC"}; - for( auto& flag : compile_flags ) argp.push_back( flag.c_str() ); + std::transform( compile_flags.begin(), compile_flags.end(), std::back_inserter(argp), [](const auto& flag ){return flag.c_str() ; } ); if( m_cxx.find("clang") != std::string::npos ) argp.push_back( "-Wno-return-type-c-linkage"); diff --git a/src/Event.cpp b/src/Event.cpp index d9535000906..8ca8c171466 100644 --- a/src/Event.cpp +++ b/src/Event.cpp @@ -10,19 +10,19 @@ using namespace AmpGen; -Event::Event( const size_t& N, const size_t& cacheSize) : +Event::Event( const unsigned& N, const unsigned& cacheSize) : m_event(N), m_cache(cacheSize) { } -Event::Event( const real_t* data, const size_t& N, const size_t& cacheSize) : +Event::Event( const real_t* data, const unsigned& N, const unsigned& cacheSize) : m_event(data, data+N), m_cache(cacheSize) { } void Event::print() const { - size_t nParticles = m_event.size()/4; - for( size_t i = 0 ; i < nParticles; ++i ){ + unsigned nParticles = m_event.size()/4; + for( unsigned i = 0 ; i < nParticles; ++i ){ double px = m_event[4*i+0]; double py = m_event[4*i+1]; double pz = m_event[4*i+2]; @@ -30,25 +30,25 @@ void Event::print() const { double s = pE*pE - px*px -py*py -pz*pz; INFO( "P["< EventType::minmax( const std::vector& indices, bool isGeV ) const +std::pair EventType::minmax( const std::vector& indices, bool isGeV ) const { - std::vector ivec( size() ); + std::vector ivec( size() ); std::iota( ivec.begin(), ivec.end(), 0 ); - double min( 0 ); - double max( motherMass() ); - for ( auto& x : indices ) min += mass( x ); + double min = 0 ; + for( auto& i : indices ) min += mass(i); + double max = motherMass(); for ( auto& x : ivec ) if ( std::find( indices.begin(), indices.end(), x ) == indices.end() ) max -= mass( x ); - return std::pair( min * min / GeV, max * max / GeV ); + return std::pair(min*min, max*max); } -std::pair EventType::count(const size_t& index) const +std::pair EventType::count(const unsigned& index) const { if( index >= size() ){ ERROR("Looking for matching particles to index = " << index << " > size of eventType"); - return std::pair(0, 0); + return std::pair(0, 0); } - std::pair rt(0,0); - for( size_t j = 0 ; j < size(); ++j ){ + std::pair rt(0,0); + for( unsigned j = 0 ; j < size(); ++j ){ if( EventType::operator[](j) == EventType::operator[](index) ){ rt.second++; if( j < index ) rt.first++; @@ -126,19 +126,19 @@ std::pair EventType::count(const size_t& index) const std::vector EventType::finalStates() const { return m_particleNames; } std::vector EventType::masses() const { return m_particleMasses; } -size_t EventType::size() const { return m_particleNames.size(); } -double EventType::mass( const size_t& index ) const { return m_particleMasses[index]; } +unsigned EventType::size() const { return m_particleNames.size(); } +double EventType::mass( const unsigned& index ) const { return m_particleMasses[index]; } double EventType::motherMass() const { return m_motherMass; } std::string EventType::mother() const { return m_mother; } -std::string EventType::operator[]( const size_t& index ) const { return m_particleNames[index]; } -std::string EventType::label( const size_t& index, bool isRoot ) const +std::string EventType::operator[]( const unsigned& index ) const { return m_particleNames[index]; } +std::string EventType::label( const unsigned& index, bool isRoot ) const { const std::string label = ParticlePropertiesList::get( m_particleNames[index] )->label(); return isRoot ? convertTeXtoROOT( label ) : label; } -std::string EventType::label( const std::vector& index, bool isRoot ) const +std::string EventType::label( const std::vector& index, bool isRoot ) const { std::string thing = ""; for ( auto& x : index ) { @@ -156,19 +156,19 @@ EventType EventType::conj( const bool& headOnly, const bool& dontConjHead ) cons return EventType( type ); } -std::vector EventType::defaultProjections(const size_t& nBins) const +std::vector EventType::defaultProjections(const unsigned& nBins) const { std::string defaultObservable = NamedParameter( "EventType::Observable", "mass2"); std::vector projections; - for ( size_t r = 2; r < size(); ++r ) { /// loop over sizes /// - std::vector> combR = nCr( size(), r ); + for ( unsigned r = 2; r < size(); ++r ) { /// loop over sizes /// + std::vector> combR = nCr( size(), r ); std::transform( combR.begin(), combR.end(), std::back_inserter(projections), [&](auto& index){ return this->projection(nBins, index, defaultObservable ); } ); } return projections; } -Projection EventType::projection(const size_t& nBins, const std::vector& indices, const std::string& observable) const +Projection EventType::projection(const unsigned& nBins, const std::vector& indices, const std::string& observable) const { bool useRootLabelling = NamedParameter("EventType::UseRootTEX", false ); auto mm = minmax(indices, true); @@ -191,7 +191,7 @@ Projection EventType::projection(const size_t& nBins, const std::vector& bool EventType::operator==( const EventType& other ) const { if ( m_mother != other.mother() || size() != other.size() ) return false; - for ( size_t i = 0; i < m_particleNames.size(); ++i ) { + for ( unsigned i = 0; i < m_particleNames.size(); ++i ) { if ( m_particleNames[i] != other[i] ) return false; } return true; @@ -203,14 +203,14 @@ std::ostream& AmpGen::operator<<( std::ostream& os, const EventType& type ) return os; } -size_t EventType::dof() const { return 3 * size() - 7; } +unsigned EventType::dof() const { return 3 * size() - 7; } std::function EventType::symmetriser() const { - std::map> particleOrdering; - for ( size_t i = 0; i < m_particleNames.size(); ++i ) + std::map> particleOrdering; + for ( unsigned i = 0; i < m_particleNames.size(); ++i ) particleOrdering[m_particleNames[i]].push_back( i ); - std::vector> shuffles; + std::vector> shuffles; for ( auto& im : particleOrdering ) if ( im.second.size() != 1 ) shuffles.push_back( im.second ); @@ -241,9 +241,9 @@ bool EventType::has( const std::string& name ) const bool EventType::isTimeDependent() const { return m_timeDependent; } -size_t EventType::eventSize() const { return 4 * size() + m_timeDependent; } +unsigned EventType::eventSize() const { return 4 * size() + m_timeDependent; } -std::pair EventType::dim() const { return m_dim; } +std::pair EventType::dim() const { return m_dim; } std::string convertTeXtoROOT( std::string input ) { diff --git a/src/FastDT.cpp b/src/FastDT.cpp index a3e7eb18fcb..9d2a068917c 100644 --- a/src/FastDT.cpp +++ b/src/FastDT.cpp @@ -4,6 +4,10 @@ using namespace AmpGen; +FastDT::FastDT( const std::string& fname ){ + //std::ifstream s(fname); +} + int FastDT::findNode( const double* event ) { int address = m_nodes.size()-1; @@ -16,9 +20,6 @@ int FastDT::findNode( const double* event ) return m_nodes[address].left; } -FastDT::FastDT( const std::string& fname ){ - //std::ifstream s(fname); -} double nnVariance(std::vector& evts, const size_t& index) { diff --git a/src/Kinematics.cpp b/src/Kinematics.cpp index ba9239d1150..937969f1097 100644 --- a/src/Kinematics.cpp +++ b/src/Kinematics.cpp @@ -11,7 +11,7 @@ using namespace AmpGen; -MomentumTransfer::MomentumTransfer( const std::vector& _p1, const std::vector& _p2 ) +MomentumTransfer::MomentumTransfer( const std::vector& _p1, const std::vector& _p2 ) : p1( _p1 ), p2( _p2 ) { for ( auto& p : p1 ) s.push_back( p ); @@ -30,13 +30,13 @@ double MomentumTransfer::Q2( const double& s, const double& s1, const double& s2 return s / 4. - ( s1 + s2 ) / 2. + ( s1 - s2 ) * ( s1 - s2 ) / ( 4 * s ); } -HelicityCosine::HelicityCosine( const std::vector& p1, const std::vector& p2, - const std::vector& pR ) +HelicityCosine::HelicityCosine( const std::vector& p1, const std::vector& p2, + const std::vector& pR ) : _i( p1 ), _j( p2 ), _pR( pR ) { } -HelicityCosine::HelicityCosine( const size_t& i, const size_t& j, const std::vector& pR ) +HelicityCosine::HelicityCosine( const unsigned& i, const unsigned& j, const std::vector& pR ) : _i( 1, i ), _j( 1, j ), _pR( pR ) { } @@ -50,12 +50,12 @@ double HelicityCosine::operator()( const Event& evt ) const return dotProduct(pi, pj, PR) / sqrt( dotProduct( pi, pi, PR ) * dotProduct( pj, pj, PR ) ); } -TLorentzVector AmpGen::pFromEvent( const Event& evt, const size_t& ref ) +TLorentzVector AmpGen::pFromEvent( const Event& evt, const unsigned& ref ) { return TLorentzVector( evt.address( 4 * ref ) ); } -TLorentzVector AmpGen::pFromEvent( const Event& evt, const std::vector& ref ) +TLorentzVector AmpGen::pFromEvent( const Event& evt, const std::vector& ref ) { double px( 0 ), py( 0 ), pz( 0 ), pE( 0 ); for ( auto& r : ref ) { @@ -144,7 +144,7 @@ void AmpGen::boost( Event& evt, const std::tuple& n, con double nz = std::get<2>( n ); double norm = sqrt( nx * nx + ny * ny + nz * nz ); - for ( size_t i = 0; i < evt.size() / 4; ++i ) { + for ( unsigned i = 0; i < evt.size() / 4; ++i ) { double nv = evt[4 * i] * nx + evt[4 * i + 1] * ny + evt[4 * i + 2] * nz; evt[4*i+0] += ( (gamma-1) * nv / norm + gamma * evt[4*i+3] * v ) * nx / norm; evt[4*i+1] += ( (gamma-1) * nv / norm + gamma * evt[4*i+3] * v ) * ny / norm; @@ -161,7 +161,7 @@ void AmpGen::rotate( Event& evt, const std::tuple& n, cons double cv = cos(v); double sv = sin(v); double norm = sqrt( nx * nx + ny * ny + nz * nz ); - for( size_t i = 0 ; i < evt.size()/4;++i){ + for( unsigned i = 0 ; i < evt.size()/4;++i){ double ix = evt[ 4*i+0]; double iy = evt[ 4*i+1]; double iz = evt[ 4*i+2]; @@ -174,7 +174,7 @@ void AmpGen::rotate( Event& evt, const std::tuple& n, cons void AmpGen::rotateBasis( Event& evt, const TVector3& p1, const TVector3& p2, const TVector3& p3 ) { - for(size_t i = 0 ; i < evt.size()/4;++i) + for(unsigned i = 0 ; i < evt.size()/4;++i) { double ex = evt[4*i+0]; double ey = evt[4*i+1]; diff --git a/src/Lineshapes/CoupledChannel.cpp b/src/Lineshapes/CoupledChannel.cpp index db183186e63..1fb61d77549 100644 --- a/src/Lineshapes/CoupledChannel.cpp +++ b/src/Lineshapes/CoupledChannel.cpp @@ -102,11 +102,11 @@ DEFINE_LINESHAPE( CoupledChannel ) Particle p( channels[i] ); DEBUG( "Adding channel ... " << p.uniqueString() << " coupling = " << NamedParameter( channels[i+1] ) ); Expression coupling = Parameter(channels[i+1], 0); - totalWidth = totalWidth + coupling * phaseSpace(s , p, p.orbital()); - totalWidthAtPole = totalWidthAtPole + coupling * phaseSpace(mass*mass, p, p.orbital()); + totalWidth = totalWidth + coupling * phaseSpace(s , p, p.L()); + totalWidthAtPole = totalWidthAtPole + coupling * phaseSpace(mass*mass, p, p.L()); ADD_DEBUG(coupling, dbexpressions); - ADD_DEBUG(phaseSpace(s,p,p.orbital() ), dbexpressions); - ADD_DEBUG(phaseSpace(mass*mass,p,p.orbital() ), dbexpressions); + ADD_DEBUG(phaseSpace(s,p,p.L() ), dbexpressions); + ADD_DEBUG(phaseSpace(mass*mass,p,p.L() ), dbexpressions); } ADD_DEBUG(totalWidth, dbexpressions); ADD_DEBUG(totalWidthAtPole, dbexpressions); diff --git a/src/Lineshapes/GenericKmatrix.cpp b/src/Lineshapes/GenericKmatrix.cpp index 179c64ba17d..c849465533e 100644 --- a/src/Lineshapes/GenericKmatrix.cpp +++ b/src/Lineshapes/GenericKmatrix.cpp @@ -27,34 +27,34 @@ DEFINE_LINESHAPE(GenericKmatrix) INFO( "kMatrix modifier " << lineshapeModifier << " particle = " << particleName ); auto tokens = split(lineshapeModifier, '.' ); DEBUG("kMatrix modifier = " << lineshapeModifier << " nTokens = " << tokens.size() ); - size_t nPoles = NamedParameter( lineshapeModifier + "::kMatrix::nPoles"); + unsigned nPoles = NamedParameter( lineshapeModifier + "::kMatrix::nPoles"); auto channels = NamedParameter(lineshapeModifier + "::kMatrix::channels").getVector(); - size_t nChannels = channels.size(); + unsigned nChannels = channels.size(); std::vector phsps; std::vector bw_phase_space; auto s0 = mass*mass; ADD_DEBUG(s, dbexpressions ); ADD_DEBUG(s0, dbexpressions ); INFO("Initialising K-matrix with : " << nChannels); - for( size_t i = 0 ; i < channels.size(); i+=1 ){ + for( unsigned i = 0 ; i < channels.size(); i+=1 ){ Particle p( channels[i] ); INFO( p.decayDescriptor() ); Expression sf = Parameter( lineshapeModifier + "::phsp::sf::"+std::to_string(i+1), 1); - phsps.emplace_back( sf * phaseSpace(s, p, p.orbital() ) ); - bw_phase_space.emplace_back( sf * phaseSpace(s0, p, p.orbital() ) ); + phsps.emplace_back( sf * phaseSpace(s, p, p.L() ) ); + bw_phase_space.emplace_back( sf * phaseSpace(s0, p, p.L() ) ); ADD_DEBUG( *phsps.rbegin(), dbexpressions); - ADD_DEBUG( phaseSpace(s0,p,p.orbital()), dbexpressions ); + ADD_DEBUG( phaseSpace(s0,p,p.L()), dbexpressions ); } Tensor non_resonant( Tensor::dim(nChannels, nChannels) ); std::vector poleConfigs; - for (size_t pole = 1; pole <= nPoles; ++pole ){ + for (unsigned pole = 1; pole <= nPoles; ++pole ){ std::string stub = lineshapeModifier + "::pole::" + std::to_string(pole); Expression mass = Parameter(stub + "::mass"); poleConfig thisPole(mass*mass); if( dbexpressions != nullptr ) dbexpressions->emplace_back(stub+"::mass", mass); Expression bw_width = 0; Expression bw_width0 = 0; - for (size_t channel = 1; channel <= nChannels; ++channel ) + for (unsigned channel = 1; channel <= nChannels; ++channel ) { Expression g = Parameter(stub+"::g::"+std::to_string(channel)); thisPole.add(g, 1); @@ -64,7 +64,7 @@ DEFINE_LINESHAPE(GenericKmatrix) bw_width = bw_width + g*g*phsps[channel-1] / mass; bw_width0 = bw_width0 + g*g*bw_phase_space[channel-1] / mass; } - for( size_t channel = 1 ; channel <= nChannels; ++channel ){ + for( unsigned channel = 1 ; channel <= nChannels; ++channel ){ Expression g = Parameter(stub+"::g::"+std::to_string(channel)); Expression BR = g*g*bw_phase_space[channel-1] / ( mass * bw_width0 ); ADD_DEBUG( BR, dbexpressions ); @@ -73,8 +73,8 @@ DEFINE_LINESHAPE(GenericKmatrix) ADD_DEBUG(bw_width0, dbexpressions); poleConfigs.push_back(thisPole); } - for(size_t ch1 = 1; ch1 <= nChannels; ++ch1){ - for( size_t ch2 = 1; ch2 <= nChannels; ++ch2 ){ + for(unsigned ch1 = 1; ch1 <= nChannels; ++ch1){ + for( unsigned ch2 = 1; ch2 <= nChannels; ++ch2 ){ auto c1 = std::to_string(ch1); auto c2 = std::to_string(ch2); if( ch1 > ch2 ) std::swap(c1,c2); @@ -97,6 +97,6 @@ DEFINE_LINESHAPE(GenericKmatrix) Tensor propagator = getPropagator(kMatrix, phsps); ADD_DEBUG_TENSOR(non_resonant, dbexpressions); Expression M; - for(size_t i = 0 ; i < nChannels; ++i) M = M + kMatrix[{i,0}] * propagator[{0,i}]; + for(unsigned i = 0 ; i < nChannels; ++i) M = M + kMatrix[{i,0}] * propagator[{0,i}]; return M ; // * phsps[0]; } diff --git a/src/Lineshapes/kMatrix.cpp b/src/Lineshapes/kMatrix.cpp index a47db3aa13f..85b4937840e 100644 --- a/src/Lineshapes/kMatrix.cpp +++ b/src/Lineshapes/kMatrix.cpp @@ -40,7 +40,7 @@ Expression AmpGen::phsp_FOCUS( const Expression& s, const double& m0, const doub std::vector AmpGen::paramVector( const std::string& name, const unsigned int& nParam ) { std::vector returnVector; - for(size_t i = 0; i < nParam; ++i ) returnVector.emplace_back( name + std::to_string(i) ); + for(unsigned i = 0; i < nParam; ++i ) returnVector.emplace_back( name + std::to_string(i) ); return returnVector; } @@ -53,8 +53,8 @@ Tensor AmpGen::getPropagator(const Tensor& kMatrix, const std::vector& poleConfigs) +Tensor AmpGen::constructKMatrix(const Expression& this_s, const unsigned& nChannels, const std::vector& poleConfigs) { Tensor kMatrix( Tensor::dim(nChannels, nChannels)); - for ( size_t i = 0; i < nChannels; ++i ) { - for ( size_t j = 0; j < nChannels; ++j ) { + for ( unsigned i = 0; i < nChannels; ++i ) { + for ( unsigned j = 0; j < nChannels; ++j ) { Expression sumOverPoles = 0; for ( auto& pole : poleConfigs ) { Expression term = ( pole.couplings[i] * pole.couplings[j] ) / ( pole.s - this_s ); @@ -119,7 +119,7 @@ DEFINE_LINESHAPE( kMatrix ) auto kMatrix = constructKMatrix( sInGeV, 5, poleConfigs); Tensor scattPart( Tensor::dim(5,5) ); - for(size_t i = 0; i < 5;++i){ + for(unsigned i = 0; i < 5;++i){ scattPart(i,0) = fScatt[i]*( 1 - s0_scatt )/( s - s0_scatt ); scattPart(0,i) = fScatt[i]*( 1 - s0_scatt )/( s - s0_scatt ); } diff --git a/src/Particle.cpp b/src/Particle.cpp index 765a936bcb5..b51f3d8309a 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -486,7 +486,7 @@ Tensor Particle::externalSpinTensor(const int& polState, DebugSymbols* db ) cons { DEBUG("Getting final state spin tensor for: " << name() << " " << spin() ); if ( spin() == 0 ) - return Tensor( std::vector( {1.} ), std::vector( {1} ) ); + return Tensor( std::vector( {1.} ), std::vector( {1} ) ); Tensor p = P(); Expression pX = p.get(0); Expression pY = p.get(1); @@ -703,7 +703,7 @@ bool Particle::isQuasiStable() const { return props()->width() < ParticlePropertiesList::getMe()->quasiStableThreshold() && name() != "gamma0"; } -unsigned int Particle::orbital() const { return m_orbital; } +unsigned Particle::L() const { return m_orbital; } int Particle::polState() const { return m_polState; } std::string Particle::name() const { return m_name; } std::string Particle::uniqueString() const { return m_uniqueString; } @@ -775,7 +775,7 @@ unsigned int Particle::matches( const Particle& other ) const if( daughter_match == 0 ) return MatchState::None; rt |= daughter_match; } - if( m_orbital != other.orbital() ) rt |= MatchState::DifferentOrbital; + if( m_orbital != other.L() ) rt |= MatchState::DifferentOrbital; if( m_polState != other.polState() ) rt |= MatchState::DifferentPolarisation; if( rt == 0 ) rt = MatchState::Exact; if( rt & MatchState::Exact && rt != MatchState::Exact ) diff --git a/src/ParticleProperties.cpp b/src/ParticleProperties.cpp index 1d0cef7a40b..a48d496b0ff 100644 --- a/src/ParticleProperties.cpp +++ b/src/ParticleProperties.cpp @@ -67,7 +67,7 @@ ParticleProperties::ParticleProperties( const std::string& pdg_string ) : m_netQ m_quarks = s[17]; m_Aformat = s[11][0]; m_chargeString = s[13]; - m_netQuarkContent.initFromString( m_quarks ); + m_netQuarkContent = QuarkContent( m_quarks ); bool spin_status = 1; if( m_JtotalSpin == "?" ) m_twoSpin = 0; else if( m_JtotalSpin.find("/") != std::string::npos ){ diff --git a/src/ParticlePropertiesList.cpp b/src/ParticlePropertiesList.cpp index 88661fc57bb..9745d94f59d 100644 --- a/src/ParticlePropertiesList.cpp +++ b/src/ParticlePropertiesList.cpp @@ -98,7 +98,7 @@ bool ParticlePropertiesList::readFile( const std::string& name ) DEBUG( "File not found: " << name ); return false; } - INFO( "Reading file: " << name ); + DEBUG( "Reading file: " << name ); processFile( name, [this]( auto& line ) { if ( line[0] == '*' ) return; ParticleProperties P( line ); diff --git a/src/Plots.cpp b/src/Plots.cpp index ac96b8bcc18..800f12af2bc 100644 --- a/src/Plots.cpp +++ b/src/Plots.cpp @@ -35,8 +35,6 @@ void AmpGen::perAmplitudePlot( const EventList& evts, } dir->cd(); - std::vector> eventData; - std::vector tmpPlots( pdf.size() * ( pdf.size() + 1 ) / 2 ); unsigned int s = 0; diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 4fc840d7a33..fc94b44c845 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -232,7 +232,7 @@ void PolarisedSum::build_probunnormalised() { DebugSymbols db; auto prob = probExpression(transitionMatrix(), convertProxies(m_pVector,[](auto& p){ return Parameter(p->name());} ), m_debug ? &db : nullptr); - m_probExpression = CompiledExpression(prob, "prob_unnormalised", std::map(), db, m_mps); + m_probExpression = CompiledExpression(prob, "prob_unnormalised", {}, db, m_mps); CompilerWrapper().compile(m_probExpression); m_probExpression.prepare(); } @@ -400,13 +400,11 @@ std::vector PolarisedSum::fitFractions(const LinearErrorPropagator& for(auto& rule : m_rules.rules()) { FitFractionCalculator pCalc(this, findIndices(m_matrixElements, rule.first), recomputeIntegrals); - INFO("Denom = [" << vectorToString( findIndices(m_matrixElements, rule.first ) , ", " ) << "]"); for(auto& process : rule.second) { if(process.head() == m_eventType.mother() && process.prefix() != m_prefix) continue; auto numeratorIndices = processIndex(m_matrixElements, process.name()); if(numeratorIndices.size() == 0 || numeratorIndices == pCalc.normSet ) continue; - INFO("Adding calculation: " << process.name() << " [" << vectorToString(numeratorIndices, ", ") << "]"); pCalc.emplace_back(process.name(), numeratorIndices); } if( pCalc.calculators.size() == 0 ) continue; diff --git a/src/QuarkContent.cpp b/src/QuarkContent.cpp index 4211402a858..bb97ac0994d 100644 --- a/src/QuarkContent.cpp +++ b/src/QuarkContent.cpp @@ -19,6 +19,21 @@ QuarkState::QuarkState() initPositions(); } +QuarkContent::QuarkContent( const std::string& str ) +{ + if ( str.find( "non-qQ" ) < str.size() ) { + m_quarks.resize( 1 ); + return; + } + auto tokens = split( replaceAll( str, "sqrt", "" ), {'(', ')', '+', '-'} ); + m_quarks.clear(); + for ( auto& token : tokens ) { + QuarkState qc( token ); + if ( !qc.isVacuum() ) m_quarks.emplace_back( qc ); + } + if ( m_quarks.size() == 0 ) m_quarks.resize( 1 ); +} + QuarkState::QuarkState( const std::string& str ) : QuarkState() { for ( auto& c : str ) { auto lc = std::tolower(c); @@ -108,21 +123,6 @@ void QuarkContent::antiThis() for ( auto& qc : m_quarks ) qc.antiThis(); } -void QuarkContent::initFromString( const std::string& str ) -{ - if ( str.find( "non-qQ" ) < str.size() ) { - m_quarks.resize( 1 ); - return; - } - auto tokens = split( replaceAll( str, "sqrt", "" ), {'(', ')', '+', '-'} ); - m_quarks.clear(); - for ( auto& token : tokens ) { - QuarkState qc( token ); - if ( !qc.isVacuum() ) m_quarks.emplace_back( qc ); - } - if ( m_quarks.size() == 0 ) m_quarks.resize( 1 ); -} - void QuarkContent::print( std::ostream& os ) const { os << "["; diff --git a/src/Spline.cpp b/src/Spline.cpp index 7fb7a6bc207..81e7de93045 100644 --- a/src/Spline.cpp +++ b/src/Spline.cpp @@ -83,6 +83,7 @@ SplineTransfer::SplineTransfer( const SplineTransfer& other ) : CacheTransfer(other.m_address, other.m_value, other.m_size) , m_transferMatrix( other.m_transferMatrix ) , m_parameters( other.m_parameters ) + , m_nKnots( other.m_nKnots ) , m_min( other.m_min ) , m_max( other.m_max ) { diff --git a/src/Tensor.cpp b/src/Tensor.cpp index 3f5d6181d2d..10c63b83ad9 100644 --- a/src/Tensor.cpp +++ b/src/Tensor.cpp @@ -22,7 +22,7 @@ Tensor::Tensor() setupCoordinates(); } -Tensor::Tensor( const std::vector& dim ) +Tensor::Tensor( const std::vector& dim ) : m_dim(dim), m_elements( nElements(), Constant( 0. ) ) { @@ -30,19 +30,19 @@ Tensor::Tensor( const std::vector& dim ) } Tensor::Tensor( const std::vector& elements ) - : m_dim( std::vector( {elements.size()} ) ) + : m_dim( std::vector( {unsigned(elements.size())} ) ) { setupCoordinates(); for(auto& element : elements) append( element ); } -Expression Tensor::get( const size_t& co ) +Expression Tensor::get( const unsigned& co ) { if ( co >= m_elements.size() ) ERROR("Element (" + std::to_string( co ) + " ) out of range (0" << ", " << m_elements.size() << ")"); return m_elements[m_symmetrisedCoordinates[co]]; } -Expression Tensor::get( const size_t& co ) const +Expression Tensor::get( const unsigned& co ) const { if ( co >= m_elements.size() ) ERROR("Element (" + std::to_string( co ) + " ) out of range (0" << ", " << m_elements.size() << ")"); @@ -52,22 +52,22 @@ Expression Tensor::get( const size_t& co ) const std::string Tensor::to_string(const ASTResolver* resolver) const { std::string value = "{"; - for(size_t i = 0 ; i < size(); ++i) + for(unsigned i = 0 ; i < size(); ++i) { value += Tensor::operator[](i).to_string(resolver) + (i == size() -1 ? "}" : ", " ) ; } return value; } -size_t Tensor::rank() const { return m_dim.size(); } +unsigned Tensor::rank() const { return m_dim.size(); } -int Tensor::metricSgn( const std::vector& coordinates ) const +int Tensor::metricSgn( const std::vector& coordinates ) const { return std::accumulate( coordinates.begin(), coordinates.end(), 1, [](auto& prod, auto& co){ return prod * ( ( co == 3) ? 1 : -1 ) ;} ); } -int Tensor::metricSgn( const size_t& index ) const { return metricSgn( coords( index ) ); } +int Tensor::metricSgn( const unsigned& index ) const { return metricSgn( coords( index ) ); } void Tensor::append( const Expression& expression ){ m_elements.emplace_back( expression ); } void Tensor::append( const real_t& value ) { m_elements.emplace_back( Constant( value )); } @@ -84,11 +84,11 @@ void Tensor::setupCoordinates() std::iota( m_uniqueElements.begin(), m_uniqueElements.end(), 0 ); } -Expression Tensor::get( const std::vector& _co ) const { return ( m_elements[index( _co )] ); } +Expression Tensor::get( const std::vector& _co ) const { return ( m_elements[index( _co )] ); } -size_t Tensor::size() const { return m_elements.size(); } +unsigned Tensor::size() const { return m_elements.size(); } -size_t Tensor::index( const std::vector& _co ) const +unsigned Tensor::index( const std::vector& _co ) const { return symmetrisedIndex(_co); // auto id = Tensor::coordinates_to_index( _co, m_dim ); @@ -96,7 +96,7 @@ size_t Tensor::index( const std::vector& _co ) const // return id; } -size_t Tensor::symmetrisedIndex( const std::vector& co ) const +unsigned Tensor::symmetrisedIndex( const std::vector& co ) const { auto id = Tensor::coordinates_to_index( co, m_dim ); if( id > m_symmetrisedCoordinates.size() ){ @@ -105,29 +105,29 @@ size_t Tensor::symmetrisedIndex( const std::vector& co ) const return m_symmetrisedCoordinates[id] ; } -const std::vector Tensor::coords( const size_t& index ) const +const std::vector Tensor::coords( const unsigned& index ) const { return Tensor::index_to_coordinates( index, m_dim ); } -std::vector Tensor::index_to_coordinates( const size_t& index, const std::vector& dim ) +std::vector Tensor::index_to_coordinates( const unsigned& index, const std::vector& dim ) { - std::vector returnValue; - size_t index_temp = index; - for(size_t j = 0; j < dim.size(); ++j ) { - size_t dproduct = 1; - for(size_t i = 0; i < dim.size() - j-1; ++i ) dproduct *= dim[dim.size()-i-1]; - size_t val = ( index_temp - ( index_temp % dproduct ) ) / dproduct; + std::vector returnValue; + unsigned index_temp = index; + for(unsigned j = 0; j < dim.size(); ++j ) { + unsigned dproduct = 1; + for(unsigned i = 0; i < dim.size() - j-1; ++i ) dproduct *= dim[dim.size()-i-1]; + unsigned val = ( index_temp - ( index_temp % dproduct ) ) / dproduct; index_temp -= dproduct * val; returnValue.push_back( val ); } return returnValue; } -size_t Tensor::coordinates_to_index( const std::vector& co, const std::vector& dim ) +unsigned Tensor::coordinates_to_index( const std::vector& co, const std::vector& dim ) { - size_t index = 0; - size_t dproduct = 1; + unsigned index = 0; + unsigned dproduct = 1; for ( int i = dim.size()-1; i >= 0; --i ) { //for ( int i = 0; i < dim.size(); ++i ) { index += co[i] * dproduct; @@ -136,12 +136,12 @@ size_t Tensor::coordinates_to_index( const std::vector& co, const std::v return index; } -std::string Tensor::coordinates_to_string( const std::vector& coordinates ) +std::string Tensor::coordinates_to_string( const std::vector& coordinates ) { return "[" + vectorToString( coordinates, ", ") + "]"; } -size_t Tensor::nElements() const +unsigned Tensor::nElements() const { return std::accumulate( m_dim.begin(), m_dim.end(), 1, [](auto& dim, auto& d){ return dim * ( d == 0 ? 1 : d ) ; } ); } @@ -153,13 +153,13 @@ const std::string Tensor::dimString() const return str + "]"; } -size_t Tensor::nDim() const { return m_dim.size(); } +unsigned Tensor::nDim() const { return m_dim.size(); } bool Tensor::rankMatches( const Tensor& other ) { bool success = true; if ( m_dim.size() != other.m_dim.size() ) return false; - for ( size_t i = 0; i < m_dim.size(); ++i ) success &= m_dim[i] == other.m_dim[i]; + for ( unsigned i = 0; i < m_dim.size(); ++i ) success &= m_dim[i] == other.m_dim[i]; return success; } @@ -176,7 +176,7 @@ Tensor AmpGen::operator+( const Tensor& t1, const Tensor& t2 ) ERROR("Addition between tensors with different number of elements " << t1.nElements() << " " << t2.nElements()); } - for ( size_t i = 0; i < t1.nElements(); ++i ) result[i] = t1[i] + t2[i]; + for ( unsigned i = 0; i < t1.nElements(); ++i ) result[i] = t1[i] + t2[i]; return result; } @@ -194,12 +194,12 @@ Tensor AmpGen::operator-( const Tensor& t1, const Tensor& t2 ) t2.print(); ERROR("Subtraction between tensors with different number of elements " << t1.nElements() << " "<< t2.nElements()); } - for ( size_t i = 0; i < t1.nElements(); ++i ) result[i] = t1[i] - t2[i]; + for ( unsigned i = 0; i < t1.nElements(); ++i ) result[i] = t1[i] - t2[i]; return result; } void Tensor::st(const bool simplify) { - for(size_t i = 0 ; i < size(); ++i ){ + for(unsigned i = 0 ; i < size(); ++i ){ m_elements[i] = make_cse( m_elements[i], simplify ); } } @@ -207,14 +207,14 @@ void Tensor::st(const bool simplify) { Tensor Tensor::conjugate() const { Tensor copy( dims() ); - for(size_t i = 0 ; i < size(); ++i ) copy[i] = fcn::conj( get(i) ); + for(unsigned i = 0 ; i < size(); ++i ) copy[i] = fcn::conj( get(i) ); return copy; } Tensor AmpGen::operator/( const Tensor& t1, const Expression& t2 ) { Tensor result( t1.dims() ); - for (size_t i = 0; i < t1.nElements(); ++i ) result[i] = t1[i] / t2; + for (unsigned i = 0; i < t1.nElements(); ++i ) result[i] = t1[i] / t2; return result; } @@ -222,7 +222,7 @@ Tensor AmpGen::operator/( const Tensor& t1, const Expression& t2 ) Tensor AmpGen::operator*( const Expression& other, const Tensor& t1 ) { Tensor result( t1.dims() ); - for (size_t i = 0; i < t1.nElements(); ++i ) result[i] = t1[i] * other; + for (unsigned i = 0; i < t1.nElements(); ++i ) result[i] = t1[i] * other; return result; } @@ -363,10 +363,10 @@ TensorProxy Tensor::operator()( const Tensor::Index& a, const Tensor::Index& b, return TensorProxy( *this, {a, b, c, d} ); } struct contractor { - size_t i; - size_t j; + unsigned i; + unsigned j; int sgn; - contractor( const size_t& i, const size_t&j, const int& sgn) : i(i),j(j),sgn(sgn) {} + contractor( const unsigned& i, const unsigned&j, const int& sgn) : i(i),j(j),sgn(sgn) {} }; @@ -378,23 +378,23 @@ TensorProxy AmpGen::operator*( const TensorProxy& t1, const TensorProxy& t2 ) const std::vector& t1_index = t1.indices(); const std::vector& t2_index = t2.indices(); - const size_t t1_size = t1.indices().size(); - const size_t t2_size = t2.indices().size(); + const unsigned t1_size = t1.indices().size(); + const unsigned t2_size = t2.indices().size(); const Tensor& t1_tensor = t1.tensor(); const Tensor& t2_tensor = t2.tensor(); - std::vector finalTensorRank; - std::vector contractionMatrix; + std::vector finalTensorRank; + std::vector contractionMatrix; - for( size_t i = 0; i < t1_size; ++i ) + for( unsigned i = 0; i < t1_size; ++i ) { if ( std::find( t2_index.begin(), t2_index.end(), t1.indices()[i] ) == t2_index.end() ) { unsummedIndices.push_back( t1.indices()[i] ); finalTensorRank.push_back( t1_tensor.dims()[i] ); } } - for( size_t i = 0; i < t2_size; ++i ) { + for( unsigned i = 0; i < t2_size; ++i ) { auto it = std::find( t1_index.begin(), t1_index.end(), t2_index[i] ); if ( it == t1_index.end() ) { unsummedIndices.push_back( t2.indices()[i] ); @@ -405,26 +405,26 @@ TensorProxy AmpGen::operator*( const TensorProxy& t1, const TensorProxy& t2 ) t2_index[i].isUpper() != it->isUpper() ? -1 : 1 ); } } - size_t nElementsInSum = 1; + unsigned nElementsInSum = 1; for ( auto& c : contractions ){ contractionMatrix.push_back( t1_tensor.dims()[c.i] ); nElementsInSum *= t1_tensor.dims()[c.i]; } Tensor value( finalTensorRank ); - size_t nElem = value.nElements(); + unsigned nElem = value.nElements(); DEBUG("Got " << t1_tensor.dims().size() << " x " << t2_tensor.dims().size() << " with " << contractions.size() << " contractions " << nElementsInSum); DEBUG(t1_tensor.dimString() << " x " << t2_tensor.dimString() << " -> " << value.dimString()); DEBUG("Contraction matrix = " << "[" << vectorToString(contractionMatrix, ", ") << "]"); - for( size_t elem = 0; elem < nElem; ++elem ) { + for( unsigned elem = 0; elem < nElem; ++elem ) { auto coords = Tensor::index_to_coordinates( elem, finalTensorRank ); - std::vector t1_coords( t1_size, 0 ); - std::vector t2_coords( t2_size, 0 ); - size_t i = 0; - size_t j = 0; + std::vector t1_coords( t1_size, 0 ); + std::vector t2_coords( t2_size, 0 ); + unsigned i = 0; + unsigned j = 0; do { - if( !isIn(contractions, i, [](const contractor& a, const size_t& b){ return a.i == b;})) { + if( std::none_of( contractions.begin(), contractions.end(), [&i](const auto& a){ return a.i == i ;} )){ t1_coords[i] = coords[j]; j++; } @@ -432,17 +432,17 @@ TensorProxy AmpGen::operator*( const TensorProxy& t1, const TensorProxy& t2 ) i = 0; j = t1_size - contractions.size(); do { - if( !isIn(contractions, i, [](const contractor& a, const size_t& b){ return a.j == b;})) { + if( std::none_of( contractions.begin(), contractions.end(), [&i](const auto& a){ return a.j == i ;} )){ t2_coords[i] = coords[j]; j++; } } while ( ++i < t2_size ); Expression elementExpression = 0; - for( unsigned int m=0; m( t1_coords.size(), 0 ); + auto t2_coords = std::vector( t1_coords.size(), 0 ); for( unsigned int j=0;j indexB ) std::swap( indexA, indexB ); - std::map< size_t, size_t > counter; - for( size_t i = 0 ; i < m_symmetrisedCoordinates.size(); ++i ){ + std::map< unsigned, unsigned > counter; + for( unsigned i = 0 ; i < m_symmetrisedCoordinates.size(); ++i ){ auto coordinates = Tensor::index_to_coordinates( i, m_dim ); /// raw coordinates of this /// if( coordinates[indexB] > coordinates[indexA] ) std::swap( coordinates[indexA], coordinates[indexB] ); @@ -529,21 +529,21 @@ void Tensor::imposeSymmetry( size_t indexA, size_t indexB) DEBUG("Imposing symmetries on " << indexA << " <--> " << indexB << " reduces size to: " << counter.size()); } -void Tensor::imposeSymmetry( std::vector indices ) +void Tensor::imposeSymmetry( std::vector indices ) { std::sort( indices.begin(), indices.end() ); - for( size_t i=0;i& co ) { return m_elements[symmetrisedIndex(co)]; } -const Expression& Tensor::operator[]( const size_t& i ) const { return m_elements[m_symmetrisedCoordinates[i]]; } -const Expression& Tensor::operator[]( const std::vector& co ) const { return m_elements[symmetrisedIndex(co)]; } +Expression& Tensor::operator[]( const unsigned& i ) { return m_elements[m_symmetrisedCoordinates[i]]; } +Expression& Tensor::operator[]( const std::vector& co ) { return m_elements[symmetrisedIndex(co)]; } +const Expression& Tensor::operator[]( const unsigned& i ) const { return m_elements[m_symmetrisedCoordinates[i]]; } +const Expression& Tensor::operator[]( const std::vector& co ) const { return m_elements[symmetrisedIndex(co)]; } TensorProxy::TensorProxy(const Tensor& tensor, const std::vector& indices) @@ -555,9 +555,9 @@ TensorProxy::TensorProxy(const Tensor& tensor, } m_indices = indices; std::vector contractions; - std::vector rt_dim; - for( size_t i = 0 ; i < indices.size(); ++i ){ - size_t j = i + 1; + std::vector rt_dim; + for( unsigned i = 0 ; i < indices.size(); ++i ){ + unsigned j = i + 1; for( ; j < indices.size(); ++j ){ if( indices[i] != indices[j] ) continue; ERROR("Tensor self-contractions not implemented yet!"); @@ -575,43 +575,43 @@ TensorProxy::TensorProxy(const Tensor& tensor, TensorProxy TensorProxy::reorder( const std::vector& indices ) { - std::vector mapping( m_indices.size() ,0 ); - for(size_t j= 0; j < indices.size(); ++j) + std::vector mapping( m_indices.size() ,0 ); + for(unsigned j= 0; j < indices.size(); ++j) { - for(size_t i = 0; i < m_indices.size(); ++i) + for(unsigned i = 0; i < m_indices.size(); ++i) { if( m_indices[j] == indices[i] ) mapping[j] = i; } } Tensor reordered( m_tensor.dims() ); - for(size_t i = 0 ; i < m_tensor.size(); ++i) + for(unsigned i = 0 ; i < m_tensor.size(); ++i) { auto coordinates = Tensor::index_to_coordinates(i,m_tensor.dims() ); - std::vector new_coordinates( m_indices.size() ); - for(size_t z = 0 ; z < m_indices.size(); ++z ) + std::vector new_coordinates( m_indices.size() ); + for(unsigned z = 0 ; z < m_indices.size(); ++z ) new_coordinates[z] = coordinates[mapping[z]]; reordered[ i ] = m_tensor[ new_coordinates ]; } return TensorProxy( reordered, indices ); } -Tensor AmpGen::Identity( const size_t& rank ) +Tensor AmpGen::Identity( const unsigned& rank ) { - Tensor id( std::vector( {rank, rank} ) ); - for (size_t i = 0; i < rank; ++i) id(i, i) = 1; + Tensor id( std::vector( {rank, rank} ) ); + for (unsigned i = 0; i < rank; ++i) id(i, i) = 1; return id; } -const Tensor AmpGen::LeviCivita( const size_t& rank ) +const Tensor AmpGen::LeviCivita( const unsigned& rank ) { - std::vector dim( rank, rank ); - std::vector indices( rank ); + std::vector dim( rank, rank ); + std::vector indices( rank ); std::iota( indices.begin(), indices.end(), 0 ); - auto permutation_sign = []( const std::vector& permutation){ + auto permutation_sign = []( const std::vector& permutation){ int product = 1; - for ( size_t i = 0; i < permutation.size() - 1; ++i ) { - for ( size_t j = i + 1; j < permutation.size(); ++j ) { + for ( unsigned i = 0; i < permutation.size() - 1; ++i ) { + for ( unsigned j = i + 1; j < permutation.size(); ++j ) { product *= ( (int)permutation[i] - (int)permutation[j] ); } } @@ -620,7 +620,7 @@ const Tensor AmpGen::LeviCivita( const size_t& rank ) int p0 = permutation_sign( indices ); Tensor result( dim ); /// create tensor of rank N /// do { - size_t index = result.index( indices ); + unsigned index = result.index( indices ); result[index] = permutation_sign( indices ) / p0; } while ( std::next_permutation( indices.begin(), indices.end() ) ); return result; @@ -639,7 +639,7 @@ std::string TensorExpression::to_string(const ASTResolver* resolver) const { return m_tensor.to_string(resolver); } void TensorExpression::resolve( ASTResolver& resolver ) const { - for( size_t i = 0 ; i < m_tensor.size(); ++i ) m_tensor[i].resolve( resolver ); + for( unsigned i = 0 ; i < m_tensor.size(); ++i ) m_tensor[i].resolve( resolver ); } complex_t TensorExpression::operator()() const { return 0 ; } diff --git a/src/Utilities.cpp b/src/Utilities.cpp index d01087d4b32..6bd5d6e3a37 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -298,7 +298,7 @@ std::string AmpGen::rtrim( std::string s ) } // trim from both ends -std::string AmpGen::trim( std::string s ) { return ltrim( rtrim( s ) ); } +std::string AmpGen::trim( const std::string& s ) { return ltrim( rtrim( s ) ); } std::string AmpGen::ltrim( std::string s ) { diff --git a/src/Vertex.cpp b/src/Vertex.cpp index 2fb2ee72535..053762c60da 100644 --- a/src/Vertex.cpp +++ b/src/Vertex.cpp @@ -98,7 +98,7 @@ Tensor AmpGen::Gamma4Vec() Tensor AmpGen::slash( const Tensor& P ) { - if ( P.dims() != std::vector({4}) ) { + if ( P.dims() != std::vector({4}) ) { ERROR( "Can only compute slash operator against vector currents" ); return Tensor(); } diff --git a/src/Wigner.cpp b/src/Wigner.cpp index 952cf5ba6ef..5a6bd9b454a 100644 --- a/src/Wigner.cpp +++ b/src/Wigner.cpp @@ -251,7 +251,7 @@ Expression AmpGen::helicityAmplitude(const Particle& particle, } } auto particle_couplings = particle.spinOrbitCouplings(false); - auto L = particle.orbital(); + auto L = particle.L(); const auto& d1 = *particle.daughter(0); const auto& d2 = *particle.daughter(1); double S = 999; From 885201652911b016a7b20361e22b92dd8ebaad08 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 24 Sep 2019 14:44:02 +0200 Subject: [PATCH 104/250] remove example that depends on functional pdfs --- examples/modern.cpp | 173 -------------------------------------------- 1 file changed, 173 deletions(-) delete mode 100644 examples/modern.cpp diff --git a/examples/modern.cpp b/examples/modern.cpp deleted file mode 100644 index e004ab8fa2e..00000000000 --- a/examples/modern.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "AmpGen/Chi2Estimator.h" -#include "AmpGen/EventList.h" -#include "AmpGen/EventType.h" -#include "AmpGen/CoherentSum.h" -#include "AmpGen/IncoherentSum.h" -#include "AmpGen/FitResult.h" -#include "AmpGen/Minimiser.h" -#include "AmpGen/MinuitParameterSet.h" -#include "AmpGen/MsgService.h" -#include "AmpGen/NamedParameter.h" -#include "AmpGen/SumPDF.h" -#include "AmpGen/Utilities.h" -#include "AmpGen/Generator.h" -#include "AmpGen/ErrorPropagator.h" -#include "AmpGen/functional/likelihood.h" -#ifdef _OPENMP - #include - #include -#endif - -#include -#include -#include - -using namespace AmpGen; - -template -FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& MPS ); - -int main( int argc, char* argv[] ) -{ - /* The user specified options must be loaded at the beginning of the programme, - and these can be specified either at the command line or in an options file. */ - OptionsParser::setArgs( argc, argv ); - - /* Parameters that have been parsed can be accessed anywhere in the program - using the NamedParameter class. The name of the parameter is the first option, - then the default value, and then the help string that will be printed if --h is specified - as an option. */ - std::string dataFile = NamedParameter("DataSample", "" , "Name of file containing data sample to fit." ); - std::string intFile = NamedParameter("IntegrationSample","" , "Name of file containing events to use for MC integration."); - std::string logFile = NamedParameter("LogFile" , "Fitter.log", "Name of the output log file"); - std::string plotFile = NamedParameter("Plots" , "plots.root", "Name of the output plot file"); - - auto bNames = NamedParameter("Branches", std::vector() - ,"List of branch names, assumed to be \033[3m daughter1_px ... daughter1_E, daughter2_px ... \033[0m" ).getVector(); - - auto pNames = NamedParameter("EventType" , "" - , "EventType to fit, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(); - - [[maybe_unused]] - size_t nThreads = NamedParameter ("nCores" , 8 , "Number of threads to use" ); - size_t seed = NamedParameter ("Seed" , 1 , "Random seed used" ); - - if( dataFile == "" ) FATAL("Must specify input with option " << italic_on << "DataSample" << italic_off ); - if( pNames.size() == 0 ) FATAL("Must specify event type with option " << italic_on << " EventType" << italic_off); - - TRandom3 rndm; - rndm.SetSeed( seed ); - gRandom = &rndm; - - INFO("LogFile: " << logFile << "; Plots: " << plotFile ); - -#ifdef _OPENMP - omp_set_num_threads( nThreads ); - INFO( "Setting " << nThreads << " fixed threads for OpenMP" ); - omp_set_dynamic( 0 ); -#endif - - /* A MinuitParameterSet is (unsurprisingly) a set of fit parameters, and can be loaded from - the parsed options. For historical reasons, this is referred to as loading it from a "Stream" */ - MinuitParameterSet MPS; - MPS.loadFromStream(); - - /* An EventType specifies the initial and final state particles as a vector that will be described by the fit. - It is typically loaded from the interface parameter EventType. */ - EventType evtType(pNames); - - /* A CoherentSum is the typical amplitude to be used, that is some sum over quasi two-body contributions - weighted by an appropriate complex amplitude. The CoherentSum is generated from the couplings described - by a set of parameters (in a MinuitParameterSet), and an EventType, which matches these parameters - to a given final state and a set of data. A common set of rules can be matched to multiple final states, - i.e. to facilitate the analysis of coupled channels. */ - CoherentSum sig(evtType, MPS); - - /* Events are read in from ROOT files. If only the filename and the event type are specified, - the file is assumed to be in the specific format that is defined by the event type, - unless the branches to load are specified in the user options */ - EventList events(dataFile, evtType, Branches(bNames), GetGenPdf(false) ); - - /* Generate events to normalise the PDF with. This can also be loaded from a file, - which will be the case when efficiency variations are included. Default number of normalisation events - is 5 million. */ - EventList eventsMC = intFile == "" ? Generator<>(evtType, &rndm).generate(2e6) : EventList(intFile, evtType, GetGenPdf(true)); - - sig.setMC( eventsMC ); - - TFile* output = TFile::Open( plotFile.c_str(), "RECREATE" ); output->cd(); - - /* Do the fit and return the fit results, which can be written to the log and contains the - covariance matrix, fit parameters, and other observables such as fit fractions */ - sig.setEvents( events ); - FitResult* fr = doFit( functional::make_likelihood(sig, events.begin(), events.end()), events, eventsMC, MPS ); - /* Calculate the `fit fractions` using the signal model and the error propagator (i.e. - fit results + covariance matrix) of the fit result, and write them to a file. - */ - auto fitFractions = sig.fitFractions( fr->getErrorPropagator() ); - - fr->addFractions( fitFractions ); - fr->writeToFile( logFile ); - output->cd(); - - /* Write out the data plots. This also shows the first example of the named arguments - to functions, emulating python's behaviour in this area */ - - auto plots = events.makeDefaultProjections(Prefix("Data"), Bins(100)); - for ( auto& plot : plots ) plot->Write(); - - output->Close(); -} - -template -FitResult* doFit( likelihoodType&& likelihood, EventList& data, EventList& mc, MinuitParameterSet& MPS ) -{ - auto time_wall = std::chrono::high_resolution_clock::now(); - auto time = std::clock(); - /* Minimiser is a general interface to Minuit1/Minuit2, - that is constructed from an object that defines an operator() that returns a double - (i.e. the likielihood, and a set of MinuitParameters. */ - Minimiser mini( likelihood, &MPS ); - mini.doFit(); - FitResult* fr = new FitResult(mini); - - auto twall_end = std::chrono::high_resolution_clock::now(); - double time_cpu = ( std::clock() - time ) / (double)CLOCKS_PER_SEC; - double tWall = std::chrono::duration( twall_end - time_wall ).count(); - INFO( "Wall time = " << tWall / 1000. ); - INFO( "CPU time = " << time_cpu ); - - /* Make the plots for the different components in the PDF, i.e. the signal and backgrounds. - The structure assumed the PDF is some SumPDF. */ - unsigned int counter = 1; - /* - for_each(likelihood.pdfs(), [&](auto& pdf){ - auto pfx = Prefix("Model_cat"+std::to_string(counter)); - auto mc_plot3 = mc.makeDefaultProjections(WeightFunction(pdf), pfx); - for( auto& plot : mc_plot3 ) - { - plot->Scale( ( data.integral() * pdf.getWeight() ) / plot->Integral() ); - plot->Write(); - } - counter++; - }); - */ - /* Estimate the chi2 using an adaptive / decision tree based binning, - down to a minimum bin population of 15, and add it to the output. */ -// Chi2Estimator chi2( data, mc, likelihood, 15 ); -// chi2.writeBinningToFile("chi2_binning.txt"); -// fr->addChi2( chi2.chi2(), chi2.nBins() ); - - fr->print(); - return fr; -} From fdbe1352e816f7683848c2ed44023cb87c0a3c04 Mon Sep 17 00:00:00 2001 From: Maurizio Martinelli Date: Tue, 24 Sep 2019 16:00:09 +0200 Subject: [PATCH 105/250] fixed compilation when omp is not available --- examples/SimFit.cpp | 48 +++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/examples/SimFit.cpp b/examples/SimFit.cpp index 14aacf18ff7..dcc7b5b69ac 100644 --- a/examples/SimFit.cpp +++ b/examples/SimFit.cpp @@ -12,7 +12,9 @@ #include "AmpGen/Kinematics.h" #include "AmpGen/Generator.h" #include "AmpGen/PolarisedSum.h" +#ifdef _OPENMP #include +#endif #include "TRandom3.h" #include "TFile.h" @@ -22,33 +24,33 @@ using namespace AmpGen; int main(int argc , char* argv[] ){ OptionsParser::setArgs( argc, argv ); - - const auto pEventType = NamedParameter("EventType", std::vector(), + + const auto pEventType = NamedParameter("EventType", std::vector(), "EventType to fit, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(); - - const auto datasets = NamedParameter("Datasets","", + + const auto datasets = NamedParameter("Datasets","", "List of data/simulated samples to fit, in the format \ \033[3m data[0] sim[0] data[1] sim[1] ... \033[0m. \nIf a simulated sample is specified FLAT, uniformly generated phase-space events are used for integrals ").getVector(); - - const std::string logFile = NamedParameter("LogFile" , "Fitter.log", + + const std::string logFile = NamedParameter("LogFile" , "Fitter.log", "Name of the output log file"); - - const std::string plotFile = NamedParameter("Plots" , "plots.root", + + const std::string plotFile = NamedParameter("Plots" , "plots.root", "Name of the output plot file"); std::vector data; - std::vector mcs; - - #ifdef _OPENMP + std::vector mcs; + + #ifdef _OPENMP size_t hwThreads = std::thread::hardware_concurrency(); size_t usThreads = NamedParameter( "nCores", hwThreads, "Number of cores to use (OpenMP only)" ); INFO("Using: " << usThreads << " / " << hwThreads << " threads" ); omp_set_num_threads(usThreads); omp_set_dynamic(0); #endif - + INFO("Output : " << logFile << " plots = " << plotFile ); - + if( pEventType.size() == 0 ) FATAL("Must specify event format as EventType \033[3m parent daughter1 daughter2 ... \033[0m in options"); const EventType eventType = EventType( pEventType ); @@ -59,12 +61,12 @@ int main(int argc , char* argv[] ){ else mcs.emplace_back( datasets[i+1], eventType, GetGenPdf(true) ); } - std::vector fcs(data.size()); - std::vector> pdfs; - - pdfs.reserve(data.size()); + std::vector fcs(data.size()); + std::vector> pdfs; - SimFit totalLL; + pdfs.reserve(data.size()); + + SimFit totalLL; MinuitParameterSet mps; mps.loadFromStream(); for(size_t i = 0; i < data.size(); ++i){ @@ -72,21 +74,21 @@ int main(int argc , char* argv[] ){ pdfs.emplace_back( make_pdf(fcs[i]) ); pdfs[i].setEvents(data[i]); auto& mc = mcs[i]; - for_each( pdfs[i].pdfs(), [&mc](auto& pdf){pdf.setMC(mc);}); + for_each( pdfs[i].pdfs(), [&mc](auto& pdf){pdf.setMC(mc);}); totalLL.add( pdfs[i] ); - } + } Minimiser mini( totalLL, &mps ); - mini.doFit(); + mini.doFit(); FitResult(mini).writeToFile("Fitter.log"); TFile* output_plots = TFile::Open( plotFile.c_str(), "RECREATE"); for( size_t i = 0 ; i < data.size(); ++i ) { INFO("Making figures for sample: " << i << " ..."); - auto dataPlots = data[i].makeDefaultProjections( Prefix("Data_"+std::to_string(i))); + auto dataPlots = data[i].makeDefaultProjections( Prefix("Data_"+std::to_string(i))); for( auto& p : dataPlots ) p->Write(); size_t counter = 0; for_each(pdfs[i].pdfs(), [&]( auto& f ){ - auto mc_plots = mcs[i].makeDefaultProjections(WeightFunction(f), + auto mc_plots = mcs[i].makeDefaultProjections(WeightFunction(f), Prefix("Model_sample_"+std::to_string(i)+"_cat"+std::to_string(counter))); for( auto& plot : mc_plots ) { From 9a2707190216d7ac1466669175dcdbb8dea029f1 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 25 Sep 2019 22:22:20 +0200 Subject: [PATCH 106/250] fix printing in AmplitudeRules to deal with radians vs degrees, warning if no rules are found for a MPS vs EventType --- README.tex.md | 23 ++++++++++++++++++++--- src/AmplitudeRules.cpp | 2 +- src/CoherentSum.cpp | 3 +++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/README.tex.md b/README.tex.md index d63604095d0..1b5023c912c 100644 --- a/README.tex.md +++ b/README.tex.md @@ -222,7 +222,7 @@ This section contains miscellaneous details on more advanced functionality, incl * [Particle Properties and Lineshape parameters](#particle-properties-and-lineshape-parameters) * [Fit parameters and expressions](#fit-parameters-and-expressions) * [Spin Formalisms](#spin-formalisms) -* [Quasi-Particles](#quasi-particles) +* [Quasiparticles](#quasiparticles) ### Python Bindings Models built into a shared library can be used in python using the following flags into ConvertToSourceCode: @@ -308,9 +308,26 @@ t2 { ``` That is specified as sets of three numbers, firstly the coupling, and then the two particle helicities. So in this example, the longitudinal amplitude is the $00$ helicity state, while the two transverse amplitudes and the sum and difference of the two other helicity amplitudes. -### Quasi-Particles - +### Quasiparticles +Quasiparticles are (semi)fictional decaying particles that can be implemented in the decay chain for a variety of different purposes. The original use case was to group some amplitudes with the same quantum numbers with couplings that want to be factorised. +For example, for the @f$I=0@f$ @f$S@f$-wave, the K matrix description may be used. The coupling from the initial state may be written as +``` +D0{K0S0,NonResS0} ... +``` +The quasiparticle _NonResS0_ can then be decayed to the final state via the K matrix lineshape(s) +``` +NonResS0[kMatrix.pole.0]{pi+,pi-} ... +NonResS0[kMatrix.pole.1]{pi+,pi-} ... +... +``` +where each of the .X is one of the terms of the (pole) production vector. +In this example, an equivalent formulation would be +``` +D0{K0S0,NonResS0[kMatrix.pole.0]{pi+,pi-}} ... +D0{K0S0,NonResS0[kMatrix.pole.1]{pi+,pi-}} ... +... +``` ## Acknowledgements The development of this software has been supported by the National Science Foundation under grant PHY-1414736 and through a subcontract under Cooperative Agreement OAC-1836650. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the developers and do not necessarily reflect the views of the National Science Foundation. diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index ad6def17097..1a4d5d9463b 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -138,7 +138,7 @@ void CouplingConstant::print() const else for ( auto& coupling : couplings ) INFO( coupling.first->name() << " x exp(i" << coupling.second->name() << ") = " << - coupling.first->mean() * exp( 1i * coupling.second->mean() * M_PI / 180. ) ); + coupling.first->mean() * exp( 1i * coupling.second->mean() * sf ) ); } std::vector> AmplitudeRules::getMatchingRules(const EventType& type, const std::string& prefix ) diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 0f0f7045ef6..e60d773c4bc 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -43,6 +43,9 @@ CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, , m_prefix( prefix ) { auto amplitudes = m_protoAmplitudes.getMatchingRules( m_evtType, prefix); + if( amplitudes.size() == 0 ){ + WARNING("The defined amplitudes don't seem to be able to be able to generate eventType: " << type); + } for( auto& amp : amplitudes ) INFO( amp.first.decayDescriptor() ); m_matrixElements.resize( amplitudes.size() ); m_normalisations.resize( m_matrixElements.size(), m_matrixElements.size() ); From 0de6006486e456e9eee34b0a147d2e5d21151cc9 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 12 Nov 2019 09:42:30 +0100 Subject: [PATCH 107/250] Add TreePhaseSpace generator --- AmpGen/AmplitudeRules.h | 84 ++++---- AmpGen/CoherentSum.h | 2 +- AmpGen/Expression.h | 8 +- AmpGen/Generator.h | 12 +- AmpGen/MinuitExpression.h | 11 +- AmpGen/Particle.h | 2 +- AmpGen/TreePhaseSpace.h | 101 ++++++++++ apps/Debugger.cpp | 7 +- apps/Generator.cpp | 22 +- doc/release.notes | 2 + options/MintDalitzSpecialParticles.csv | 2 + options/mass_width.csv | 2 +- src/AmplitudeRules.cpp | 155 +++++++------- src/CoherentSum.cpp | 7 +- src/Expression.cpp | 8 +- src/Lineshapes/Isotensor.cpp | 7 +- src/MinuitExpression.cpp | 7 +- src/MinuitParameter.cpp | 27 +-- src/MinuitParameterSet.cpp | 14 +- src/Particle.cpp | 17 +- src/TreePhaseSpace.cpp | 267 +++++++++++++++++++++++++ src/Utilities.cpp | 9 +- test/test_AmplitudeRules.cpp | 2 +- 23 files changed, 595 insertions(+), 180 deletions(-) create mode 100644 AmpGen/TreePhaseSpace.h create mode 100644 src/TreePhaseSpace.cpp diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index f73e2508c85..67207260016 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -16,77 +16,83 @@ namespace AmpGen { - class AmplitudeRules; class MinuitParameter; + class MinuitExpression; class MinuitParameterSet; - class CouplingConstant; - class AmplitudeRule + class Coupling { public: - AmplitudeRule(MinuitParameter* re, MinuitParameter* im); + Coupling(MinuitParameter* re, MinuitParameter* im); + Coupling(MinuitExpression* expression); std::string name() const { return m_name; } std::string head() const { return m_particle.name(); } std::string prefix() const { return m_prefix; } EventType eventType() const; - friend class CouplingConstant; - friend class AmplitudeRules; - + MinuitParameter* x() const { return m_re; } + MinuitParameter* y() const { return m_im; } + complex_t operator()() const; + Expression to_expression() const; + const Particle& particle() const { return m_particle ; } + bool isCartesian() const { return m_isCartesian; } private: - std::string m_prefix = {""}; - std::string m_name = {""}; - MinuitParameter* m_re = {nullptr}; - MinuitParameter* m_im = {nullptr}; - Particle m_particle; + std::string m_prefix = {""}; + std::string m_name = {""}; + MinuitParameter* m_re = {nullptr}; + MinuitParameter* m_im = {nullptr}; + MinuitExpression* m_expr = {nullptr}; + Particle m_particle; + bool m_isCartesian = {true}; + double m_sf = {1}; }; - class AmplitudeRules - { - public: - AmplitudeRules() = default; - AmplitudeRules( const MinuitParameterSet& mps ); - std::vector rulesForDecay(const std::string& head, const std::string& prefix=""); - bool hasDecay( const std::string& head ); - std::map> rules(); - std::vector> getMatchingRules( - const EventType& type, const std::string& prefix="" ); - std::vector processesThatProduce(const Particle& particle) const; - - private: - std::map> m_rules; - }; - - class CouplingConstant + class TotalCoupling { public: - CouplingConstant() = default; - CouplingConstant( const CouplingConstant& other, const AmplitudeRule& pA); - CouplingConstant( const AmplitudeRule& pA); + TotalCoupling() = default; + TotalCoupling( const TotalCoupling& other, const Coupling& pA); + TotalCoupling( const Coupling& pA); std::complex operator()() const; Expression to_expression() const; void print() const; - std::pair operator[]( const size_t& index ) { return couplings[index]; } + Coupling operator[]( const size_t& index ) { return couplings[index]; } bool isFixed() const; bool contains( const std::string& name ) const; - std::vector> couplings; + size_t size() const { return couplings.size(); } + std::vector::const_iterator begin() const { return couplings.begin() ; } + std::vector::const_iterator end() const { return couplings.end() ; } + private: + std::vector couplings; + }; + + class AmplitudeRules + { + public: + AmplitudeRules() = default; + AmplitudeRules( const MinuitParameterSet& mps ); + std::vector rulesForDecay(const std::string& head, const std::string& prefix=""); + bool hasDecay( const std::string& head ); + std::map> rules(); + std::vector> getMatchingRules( + const EventType& type, const std::string& prefix="" ); + std::vector processesThatProduce(const Particle& particle) const; private: - bool isCartesian = {true}; - double sf = {1}; + std::map> m_rules; }; template struct TransitionMatrix { TransitionMatrix() = default; TransitionMatrix(const Particle& dt, - const CouplingConstant& coupling, + const TotalCoupling& coupling, const CompiledExpression & amp) : decayTree(dt), coupling(coupling), amp(amp) {} TransitionMatrix(Particle& dt, - const CouplingConstant& coupling, + const TotalCoupling& coupling, const MinuitParameterSet& mps, const std::map& evtFormat, const bool& debugThis=false) : @@ -99,7 +105,7 @@ namespace AmpGen const std::string decayDescriptor() const { return decayTree.decayDescriptor() ; } Particle decayTree; - CouplingConstant coupling; + TotalCoupling coupling; complex_t coefficient; DebugSymbols db; CompiledExpression amp; diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index 740ea2b637e..a8e47dfe933 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -108,7 +108,7 @@ namespace AmpGen bool m_verbosity = {false}; ///< Flag for verbose printing std::string m_objCache = {""}; ///< Directory that contains (cached) amplitude objects std::string m_prefix = {""}; ///< Prefix for matrix elements - void addMatrixElement( std::pair& particleWithCoupling, const MinuitParameterSet& mps ); + void addMatrixElement( std::pair& particleWithCoupling, const MinuitParameterSet& mps ); }; } // namespace AmpGen diff --git a/AmpGen/Expression.h b/AmpGen/Expression.h index fef0e36b8c6..2ffaeca166b 100644 --- a/AmpGen/Expression.h +++ b/AmpGen/Expression.h @@ -135,10 +135,10 @@ namespace AmpGen std::string to_string(const ASTResolver* resolver=nullptr) const; IExpression* get() const; void resolve( ASTResolver& resolver ) const; - Expression operator+=( const Expression& other ) const; - Expression operator*=( const Expression& other ) const; - Expression operator-=( const Expression& other ) const; - Expression operator/=( const Expression& other ) const; + Expression operator+=( const Expression& other ); + Expression operator*=( const Expression& other ); + Expression operator-=( const Expression& other ); + Expression operator/=( const Expression& other ); Expression operator-() const; complex_t operator()() const; diff --git a/AmpGen/Generator.h b/AmpGen/Generator.h index 87e1243775e..0b6f1ed4ae6 100644 --- a/AmpGen/Generator.h +++ b/AmpGen/Generator.h @@ -81,7 +81,7 @@ namespace AmpGen if ( normalisationConstant == 0 ) { double max = 0; for ( auto& evt : mc ) { - double value = pdf.prob_unnormalised( evt ); + double value = pdf.prob_unnormalised( evt ) / evt.genPdf(); if ( value > max ) max = value; } normalisationConstant = max * 1.5; @@ -89,10 +89,10 @@ namespace AmpGen } auto previousSize = list.size(); t_acceptReject.start(); -#ifdef _OPENMP -#pragma omp parallel for -#endif - for ( size_t i=0;i< mc.size(); ++i ) mc[i].setGenPdf(pdf.prob_unnormalised(mc[i])); + #ifdef _OPENMP + #pragma omp parallel for + #endif + for ( size_t i=0;i< mc.size(); ++i ) mc[i].setGenPdf(pdf.prob_unnormalised(mc[i]) / mc[i].genPdf()); for( auto& evt : mc ){ if ( evt.genPdf() > normalisationConstant ) { @@ -105,7 +105,7 @@ namespace AmpGen t_acceptReject.stop(); double time = std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); double efficiency = 100. * ( list.size() - previousSize ) / (double)m_generatorBlock; - pb.print( double(list.size()) / double(N), " ε[gen] = " + mysprintf("%.2f",efficiency) + "% , " + std::to_string(int(time/1000.)) + " seconds" ); + pb.print( double(list.size()) / double(N), " ε[gen] = " + mysprintf("%.4f",efficiency) + "% , " + std::to_string(int(time/1000.)) + " seconds" ); if ( list.size() == previousSize ) { ERROR( "No events generated, PDF: " << typeof() << " is likely to be malformed" ); break; diff --git a/AmpGen/MinuitExpression.h b/AmpGen/MinuitExpression.h index f6f246202dc..0e4dde4ac93 100644 --- a/AmpGen/MinuitExpression.h +++ b/AmpGen/MinuitExpression.h @@ -16,15 +16,14 @@ namespace AmpGen { public: MinuitExpression( const std::vector& tokens, MinuitParameterSet* mps ); - double getVal() const { return std::real( m_expression() ); } - double mean() const override { return getVal(); } - operator double() const override { return getVal(); } - ~MinuitExpression() override = default; - bool isGood() const { return m_isGood; } + double mean() const override; + complex_t getVal() const; + Expression expression() const { return m_expression; } + operator double() const override; + ~MinuitExpression() override; private: Expression m_expression; - bool m_isGood; }; } // namespace AmpGen diff --git a/AmpGen/Particle.h b/AmpGen/Particle.h index 7c53cfbce9d..1318d90df42 100644 --- a/AmpGen/Particle.h +++ b/AmpGen/Particle.h @@ -115,6 +115,7 @@ namespace AmpGen /// (Quasi) Constructor that returns the (quasi)CP conjugated amplitude. The full behaviour of the amplitude is made more complicated by the ordering convention. Particle conj(bool invertHead = true, bool reorder = true); + static bool isValidDecayDescriptor( const std::string& decayDescriptor ); /// Set the orbital quantum number 'L' for this decay. void setOrbital( const unsigned int& orbital ); @@ -266,7 +267,6 @@ namespace AmpGen }; /// matches Check the matching between two decay chains, according to the MatchState enum. unsigned int matches( const Particle& other ) const; - private: const ParticleProperties* m_props = {nullptr}; ///< Particle Properties from the PDG std::string m_name = {""}; ///< Name of the particle diff --git a/AmpGen/TreePhaseSpace.h b/AmpGen/TreePhaseSpace.h new file mode 100644 index 00000000000..e3aa8c1186a --- /dev/null +++ b/AmpGen/TreePhaseSpace.h @@ -0,0 +1,101 @@ +#ifndef AMPGEN_TREEPHASESPACE_H +#define AMPGEN_TREEPHASESPACE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "AmpGen/EventType.h" +#include "AmpGen/PhaseSpace.h" +#include "AmpGen/Particle.h" + +#include +#include + +namespace AmpGen +{ + class Particle; + class Event; + /** @class TreePhaseSpace + @brief Generator of events where the phase space is decomposed into a series of subtrees. + @decription Generates events using the decomposition of the phase space + into a series of two-body phase spaces, where the invariant mass of the two-body space + can be generated according to, for example, a simplified Breit-Wigner model. + This can then be used to generate a more complex model using accept-reject, which + allows for a much more efficient generation of narrow peaks. + + Currently, each of the available channels is given the same weight relative to phase space, + ideally feedback could be given from the generator phase to focus on the more efficient channels, + i.e. those that have larger contributions to the full amplitude. + */ + class TreePhaseSpace + { + public: + struct Vertex + { + Vertex() = default; + Vertex(const Particle& particle, const double& min); + Vertex(const Particle& particle, const double& min, const double& max, const bool& isStable); + double p() const; + double genBW() const; + double BW(const double& si) const; + double weight() const; + double maxWeight() const; + double genPdf(const Event& event) const; + void generate(); + void print(const unsigned& offset = 0) const; + void place(Event& event); + Event event(const unsigned& eventSize, const unsigned& cacheSize=0); + void generate_full_event_description(const TLorentzVector& parentVector); + void setRhoMax(); + void setRandom(TRandom3* rnd); + static Vertex make(const Particle& particle, Vertex* parent = nullptr); + Particle particle; + double min = {0}; + double max = {0}; + double rhoMax = {0}; + double s = {0}; + bool isStable = {false}; + bool isBW = {true}; + unsigned index = {999}; + double bwMass = {0}; + double bwWidth = {0}; + double phiMin = {0}; + double phiMax = {0}; + double w = {0}; + double weightMax= {0}; + std::shared_ptr left = {nullptr}; + std::shared_ptr right = {nullptr}; + TRandom3* rand = {nullptr}; + std::vector indices; + TLorentzVector mom; + }; + + explicit TreePhaseSpace(const EventType& type); + TreePhaseSpace(const Particle& decayChain, const EventType& type, TRandom* rndm = nullptr ); + TreePhaseSpace(const std::vector& decayChains, const EventType& type, TRandom* rndm = nullptr); + + void setRandom( TRandom* rand ); + Event makeEvent( const unsigned& cacheSize = 0 ); + size_t size() const; + EventType eventType() const ; + double genPdf( const Event& event) const ; + const Vertex& operator[](const unsigned i) const { return m_top[i]; } + + private: + std::vector m_top; + TRandom3* m_rand = {nullptr}; + EventType m_type; ///< EventType to generate + std::discrete_distribution<> m_dice; ///< + std::vector m_weights; + std::mt19937 m_gen; + }; +} // namespace AmpGen + +#endif diff --git a/apps/Debugger.cpp b/apps/Debugger.cpp index 01b0ca9bfd3..2257f1a54a8 100644 --- a/apps/Debugger.cpp +++ b/apps/Debugger.cpp @@ -73,6 +73,7 @@ void invert( MinuitParameter* param, MinuitParameterSet& mps ) if( props != 0 ) new_name = props->anti().name() + "_" + tokens[1]; } } + //INFO( param->name() << " " << sgn ); mps.rename( param->name(), new_name ); if( sgn == -1 ) param->setCurrentFitVal( -1 * param->mean() ); } @@ -82,10 +83,9 @@ template void print( const Event& event, const MatrixElem { for ( auto& mE : matrixElements ) { INFO( mE.decayDescriptor() << " " << mE.coupling() ); - auto terms = mE.coupling.couplings; if ( verbose ) { - for ( auto& term : terms ) { - INFO( "--> " << term.first->name() << " = (" << term.first->mean() * cos( term.second->mean() ) << " + i " << term.first->mean() * sin( term.second->mean() ) << ")" ); + for ( auto& term : mE.coupling ) { + INFO( "--> " << term.particle().decayDescriptor() << " = " << term() ); } mE.amp.debug( event.address() ); } @@ -121,6 +121,7 @@ int main( int argc, char** argv ) INFO("Using verbose mode: " << verbose ); AmpGen::MinuitParameterSet MPS; MPS.loadFromStream(); + if ( NamedParameter( "conj", false ) == true ) { eventType = eventType.conj(false); for ( auto& param : MPS ) invert( param, MPS ); diff --git a/apps/Generator.cpp b/apps/Generator.cpp index 07137d0defb..afc562e898b 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -26,11 +26,12 @@ #include "AmpGen/NamedParameter.h" #include "AmpGen/PolarisedSum.h" #include "AmpGen/OptionsParser.h" +#include "AmpGen/TreePhaseSpace.h" #include "AmpGen/enum.h" using namespace AmpGen; -namespace AmpGen { make_enum(generatorType, CoherentSum, PolarisedSum, FixedLib, RGenerator) } +namespace AmpGen { make_enum(generatorType, CoherentSum, PolarisedSum, FixedLib, RGenerator, TreePhaseSpace) } struct FixedLibPDF { void* lib = {nullptr}; @@ -73,10 +74,11 @@ int main( int argc, char** argv ) int seed = NamedParameter ("Seed" , 0, "Random seed used in event Generation" ); std::string outfile = NamedParameter("Output" , "Generate_Output.root" , "Name of output file" ); auto genType = NamedParameter( "Type", generatorType::CoherentSum, optionalHelpString("Generator configuration to use:", - { {"CoherentSum" , "Full phase-space generator with (pseudo)scalar amplitude"} - , {"PolarisedSum", "Full phase-space generator with particles carrying spin in the initial/final states"} - , {"FixedLib" , "Full phase-space generator with an amplitude from a precompiled library"} - , {"RGenerator" , "Recursive phase-space generator for intermediate (quasi)stable states such as the D-mesons"} } ) ); + { {"CoherentSum" , "Full phase-space generator with (pseudo)scalar amplitude"} + , {"PolarisedSum" , "Full phase-space generator with particles carrying spin in the initial/final states"} + , {"FixedLib" , "Full phase-space generator with an amplitude from a precompiled library"} + , {"RGenerator" , "Recursive phase-space generator for intermediate (quasi)stable states such as the D-mesons"} + , {"TreePhaseSpace" , "Recursive phase-space generator with generic handling of intermediate states."} } ) ); std::string lib = NamedParameter("Library","","Name of library to use for a fixed library generation"); size_t nBins = NamedParameter ("nBins" ,100, "Number of bins for monitoring plots." ); @@ -119,12 +121,20 @@ int main( int argc, char** argv ) signalGenerator.setRandom( &rand ); signalGenerator.fillEventList( sig, accepted, nEvents ); } + else if ( genType == generatorType::TreePhaseSpace ) { + CoherentSum sig( eventType, MPS, "" ); + std::vector channels; + for( auto& chain : sig.matrixElements() ) channels.push_back( chain.decayTree ); + Generator signalGenerator(channels, eventType, &rand); + signalGenerator.setRandom( &rand ); + signalGenerator.fillEventList( sig, accepted, nEvents ); + } else if ( genType == generatorType::FixedLib ) { Generator<> signalGenerator( eventType ); signalGenerator.setRandom( &rand ); signalGenerator.setBlockSize( blockSize ); signalGenerator.setNormFlag( false ); - FixedLibPDF pdf( lib ); + FixedLibPDF pdf( lib ); signalGenerator.fillEventList( pdf, accepted, nEvents ); } else { diff --git a/doc/release.notes b/doc/release.notes index 73ce7baa822..3993a3d4296 100644 --- a/doc/release.notes +++ b/doc/release.notes @@ -3,6 +3,8 @@ ! Responsible : Tim Evans ! Purpose : !----------------------------------------------------------------------------- +!=================== AmpGen v1r2 2019-11-12 ================== + - New phase space Generator TreePhaseSpace for producing narrow resonances. !=================== AmpGen v1r2 2019-08-13 ================== - Tagged to match results in Gauss/LbAmpGen v49r14+ - Improved thread support for CoherentSum diff --git a/options/MintDalitzSpecialParticles.csv b/options/MintDalitzSpecialParticles.csv index dc6c5866d3d..33ce6845fce 100644 --- a/options/MintDalitzSpecialParticles.csv +++ b/options/MintDalitzSpecialParticles.csv @@ -46,4 +46,6 @@ 1.272E+03 ,7.0E+00,7.0E+00,9.0E+01 ,2.0E+01,2.0E+01,1/2, ,1 ,+, ,F, 998200, +, ,R,Ka ,uS 1.272E+03 ,7.0E+00,7.0E+00,9.0E+01 ,2.0E+01,2.0E+01,1/2, ,1 ,+, ,F, 998201, +, ,R,Kb ,uS 1.86484E+03 ,1.7E-01,1.7E-01,1.605E-09 ,6.0E-12,6.0E-12,1/2, ,0 ,-, ,F, 998421, 0, ,R,D~ ,cU +3.8948E+03 ,1.1E-02,1.1E-02,2.96E+00 ,2.1E-03,2.1E-03,1 ,+,1 ,+,-, , 999443, 0, ,R,Z(c)(3900) ,cCuU +3.8948E+03 ,1.1E-02,1.1E-02,2.96E+00 ,2.1E-03,2.1E-03,1 ,+,1 ,+,-, , 999444, +, ,R,Z(c)(3900) ,cCuD *** diff --git a/options/mass_width.csv b/options/mass_width.csv index 61963edd964..2895a7b12ac 100644 --- a/options/mass_width.csv +++ b/options/mass_width.csv @@ -378,7 +378,7 @@ 2.4601E+03 ,2.6E+00,3.5E+00,3.7E+01 ,6.0E+00,6.0E+00,1/2, ,2 ,+, ,B, 415, +, ,R,D(2)*(2460) ,cD 2.637E+03 ,6.0E+00,6.0E+00,15 ,-1 ,-1 ,1/2, ,? ,?, ,F, , +, ,S,D*(2640) ,cD 1.96849E+03 ,3.4E-01,3.4E-01,1.325E-09 ,1.9E-11,1.9E-11,0 , ,0 ,-, ,B, 431, +, ,R,D(s) ,cS -2.1123E+03 ,5.0E-01,5.0E-01,-1 ,-1 ,-1 ,0 , ,? ,?, ,B, 433, +, ,R,D(s)* ,cS +2.1123E+03 ,5.0E-01,5.0E-01,-1 ,-1 ,-1 ,0 , ,1 ,-, ,B, 433, +, ,R,D(s)* ,cS 2.3178E+03 ,6.0E-01,6.0E-01,10 ,-1 ,-1 ,0 , ,0 ,+, ,B, 10431, +, ,R,D(s0)*(2317) ,cS 2.4596E+03 ,6.0E-01,6.0E-01,6.3 ,-1 ,-1 ,0 , ,1 ,+, ,B, 20433, +, ,R,D(s1)(2460) ,cS 2.5354E+03 ,6.0E-01,6.0E-01,2.5 ,-1 ,-1 ,0 , ,1 ,+, ,B, 10433, +, ,R,D(s1)(2536) ,cS diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index 1a4d5d9463b..c2d81d2e314 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -8,6 +8,7 @@ #include #include "AmpGen/MinuitParameter.h" +#include "AmpGen/MinuitExpression.h" #include "AmpGen/MinuitParameterSet.h" #include "AmpGen/MsgService.h" #include "AmpGen/Particle.h" @@ -17,7 +18,13 @@ using namespace AmpGen; using namespace std::complex_literals; -AmplitudeRule::AmplitudeRule(MinuitParameter* re, MinuitParameter* im ) : +namespace AmpGen +{ + make_enum(coordinateType, cartesian, polar) + make_enum(angType, deg, rad) +} + +Coupling::Coupling(MinuitParameter* re, MinuitParameter* im) : m_re(re), m_im(im) { @@ -32,29 +39,54 @@ AmplitudeRule::AmplitudeRule(MinuitParameter* re, MinuitParameter* im ) : ERROR("Ill-formed decay descriptor: " << m_name ); } m_particle = Particle(m_name); + coordinateType coord = NamedParameter("CouplingConstant::Coordinates", coordinateType::cartesian); + angType degOrRad = NamedParameter("CouplingConstant::AngularUnits", angType::rad); + m_isCartesian = true; + if( coord == coordinateType::polar ) m_isCartesian = false; + else if ( coord != coordinateType::cartesian){ + FATAL("Coordinates for coupling constants must be either cartesian or polar"); + } + if ( degOrRad == angType::deg) m_sf = M_PI / 180; + else if ( degOrRad != angType::rad){ + FATAL("TotalCoupling::AngularUnits must be either rad or deg"); + } } +Coupling::Coupling(MinuitExpression* expression) : + m_name(expression->name()), + m_expr(expression), + m_particle(m_name){} + AmplitudeRules::AmplitudeRules( const MinuitParameterSet& mps ) { for ( auto& it_re : mps ) { - if ( it_re->name().find("_Re") == std::string::npos ) continue; - auto it_im = mps.find(replaceAll( it_re->name(), "_Re","_Im") ); - if( it_im == nullptr ){ - ERROR("Cannot find matching imaginary part / phase for: " << it_re->name() ); - continue; + if ( it_re->name().find("_Re") != std::string::npos ){ + auto it_im = mps.find(replaceAll( it_re->name(), "_Re","_Im") ); + if( it_im == nullptr ){ + ERROR("Cannot find matching imaginary part / phase for: " << it_re->name() ); + continue; + } + Coupling p(it_re, it_im); + m_rules[p.head()].emplace_back(p); + } + else if( it_re->name().find("_Im") == std::string::npos ){ + bool isCoupling = Particle::isValidDecayDescriptor( it_re->name() ); + if( isCoupling ){ + MinuitExpression* expression = dynamic_cast( it_re ); + INFO("Constructing: " << expression << " " << it_re->name() ); + if( expression != nullptr ){ + Coupling p(expression); + m_rules[p.head()].emplace_back(p); + } + } } - auto p = AmplitudeRule(it_re, it_im ); - m_rules[p.head()].emplace_back(p); } } -CouplingConstant::CouplingConstant( const CouplingConstant& other, - const AmplitudeRule& pA) : - couplings(other.couplings ), - isCartesian(other.isCartesian), - sf(other.sf) +TotalCoupling::TotalCoupling(const TotalCoupling& other, const Coupling& pA) : + couplings(other.couplings) { - couplings.emplace_back( pA.m_re, pA.m_im ); + couplings.emplace_back(pA); } @@ -63,21 +95,21 @@ bool AmplitudeRules::hasDecay(const std::string& head) return m_rules.find(head) != m_rules.end(); } -std::vector AmplitudeRules::rulesForDecay(const std::string& head, const std::string& prefix) +std::vector AmplitudeRules::rulesForDecay(const std::string& head, const std::string& prefix) { - if(!hasDecay(head)) return std::vector(); + if(!hasDecay(head)) return std::vector(); if( prefix == "" )return m_rules[head]; - std::vector rt = m_rules[head]; + std::vector rt = m_rules[head]; rt.erase( std::remove_if( std::begin(rt), std::end(rt), [&prefix](auto& p){ return p.prefix() != prefix; } ) ); return rt; } -std::map> AmplitudeRules::rules() +std::map> AmplitudeRules::rules() { return m_rules; } -EventType AmplitudeRule::eventType() const +EventType Coupling::eventType() const { Particle particle( m_name ); std::vector particleNames = { particle.name() }; @@ -87,77 +119,54 @@ EventType AmplitudeRule::eventType() const return EventType( particleNames ); } -namespace AmpGen +TotalCoupling::TotalCoupling(const Coupling& pA) { - make_enum(coordinateType, cartesian, polar) - make_enum(angType, deg, rad) + couplings.emplace_back(pA); } -CouplingConstant::CouplingConstant(const AmplitudeRule& pA) +std::complex Coupling::operator()() const { - couplings.emplace_back(pA.m_re,pA.m_im); - coordinateType coord = NamedParameter("CouplingConstant::Coordinates", coordinateType::cartesian); - angType degOrRad = NamedParameter("CouplingConstant::AngularUnits", angType::rad); - if( coord == coordinateType::polar ) isCartesian = false; - else if ( coord != coordinateType::cartesian){ - FATAL("Coordinates for coupling constants must be either cartesian or polar"); - } - if ( degOrRad == angType::deg) sf = M_PI / 180; - else if ( degOrRad != angType::rad){ - FATAL("CouplingConstant::AngularUnits must be either rad or deg"); - } + return m_expr != nullptr ? m_expr->getVal() : ( m_isCartesian ? complex_t( m_re->mean(), m_im->mean() ) : m_re->mean() * exp( 1i* m_sf * m_im->mean() ) ); } -std::complex CouplingConstant::operator()() const +Expression Coupling::to_expression() const { - return isCartesian ? - std::accumulate( couplings.begin(), couplings.end(), complex_t(1,0), - [](auto& prod, auto& coupling){ return prod * complex_t( coupling.first->mean(), coupling.second->mean() ) ; } ) - : std::accumulate( couplings.begin(), couplings.end(), complex_t(1,0), - [this](auto& prod, auto& coupling){ return prod * coupling.first->mean() * exp( 1i* this->sf * coupling.second->mean() ) ; } ); + return m_expr != nullptr ? m_expr->expression() : ( m_isCartesian ? Parameter(m_re->name()) + 1i * Parameter(m_im->name()) : Parameter( m_re->name() ) * fcn::exp( 1i * m_sf * Parameter(m_im->name()) ) ); } -Expression CouplingConstant::to_expression() const +std::complex TotalCoupling::operator()() const { - if ( isCartesian ) { - return std::accumulate( couplings.begin(), couplings.end(), Expression(1), - [](auto& prod, auto& p){ return prod * ( Parameter(p.first->name()) + 1i*Parameter(p.second->name() ) ) ; } ); - } else { - auto it = std::accumulate( couplings.begin(), couplings.end(), std::pair(1,0), - [](auto& prod, auto& p) -> std::pair { - return std::make_pair( prod.first * Parameter( p.first->name() ), prod.second + Parameter( p.second->name() ) ); } ); - return it.first * fcn::exp( 1i*sf*it.second ); - } + return std::accumulate( couplings.begin(), couplings.end(), complex_t(1,0), [](auto& prod, auto& coupling ){ return prod * coupling() ; } ); +} + +Expression TotalCoupling::to_expression() const +{ + return std::accumulate( couplings.begin(), couplings.end(), Expression(1), [](auto& prod, auto& coupling ){ return prod * coupling.to_expression(); } ); } -void CouplingConstant::print() const +void TotalCoupling::print() const { - INFO( couplings[0].first->name() << " (" << isCartesian << ") = " << ( *this )() ); - if ( isCartesian ) - for ( auto& coupling : couplings ) INFO( coupling.first->name() + " i " + coupling.second->name() ); - else - for ( auto& coupling : couplings ) - INFO( coupling.first->name() << " x exp(i" << coupling.second->name() << ") = " << - coupling.first->mean() * exp( 1i * coupling.second->mean() * sf ) ); + INFO( this->operator()() << " -> " ); + for( const auto& coupling :*this ) INFO( coupling.to_expression() << " = " << coupling() ); } -std::vector> AmplitudeRules::getMatchingRules(const EventType& type, const std::string& prefix ) +std::vector> AmplitudeRules::getMatchingRules(const EventType& type, const std::string& prefix ) { auto rules = rulesForDecay( type.mother() ); - std::vector> rt; + std::vector> rt; for ( auto& rule : rules ) { if ( rule.prefix() != prefix ) continue; - std::vector> tmpParticles; + std::vector> tmpParticles; auto fs = type.finalStates(); - tmpParticles.emplace_back( Particle( rule.name(), fs ), CouplingConstant(rule) ); + tmpParticles.emplace_back( Particle( rule.name(), fs ), TotalCoupling(rule) ); do { - std::vector> newTmpParticles; - for ( auto& particleWithCouplingConstant : tmpParticles ) { - auto protoParticle = particleWithCouplingConstant.first; - auto coupling = particleWithCouplingConstant.second; + std::vector> newTmpParticles; + for ( auto& particleWithTotalCoupling : tmpParticles ) { + auto protoParticle = particleWithTotalCoupling.first; + auto coupling = particleWithTotalCoupling.second; auto protoFinalStates = protoParticle.getFinalStateParticles(); if ( protoFinalStates.size() == type.size() ) { - rt.emplace_back( particleWithCouplingConstant ); + rt.emplace_back( particleWithTotalCoupling ); continue; } std::string nameToExpand = protoParticle.uniqueString(); @@ -167,7 +176,7 @@ std::vector> AmplitudeRules::getMatchingRu for ( auto& subTree : expandedRules ) { auto expanded_amplitude = replaceAll( nameToExpand, ifs->name(), subTree.name() ); auto fs2 = type.finalStates(); - newTmpParticles.emplace_back( Particle( expanded_amplitude, fs2 ), CouplingConstant( coupling, subTree) ); + newTmpParticles.emplace_back( Particle( expanded_amplitude, fs2 ), TotalCoupling( coupling, subTree) ); } break; // we should only break if there are rules to be expanded ... } @@ -185,15 +194,13 @@ std::vector> AmplitudeRules::getMatchingRu return rt; } -bool CouplingConstant::isFixed() const +bool TotalCoupling::isFixed() const { - return std::all_of( couplings.begin(), couplings.end(), - [](auto& c){ return c.first->isFixed() && c.second->isFixed() ; } ); + return std::all_of(begin(), end(), [](auto& c){ return c.x()->isFixed() && c.y()->isFixed() ; } ); } -bool CouplingConstant::contains( const std::string& label ) const +bool TotalCoupling::contains( const std::string& label ) const { - return std::any_of( couplings.begin(), couplings.end(), - [&label](auto& c){ return c.first->name().find(label) != std::string::npos ; } ); + return std::any_of(begin(), end(), [&label](auto& c){ return c.x()->name().find(label) != std::string::npos ; } ); } diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index e60d773c4bc..0db0cb76e90 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -124,9 +124,10 @@ void CoherentSum::debug( const Event& evt, const std::string& nameMustContain ) auto A = me(evt); INFO( std::setw(70) << me.decayTree.uniqueString() << " A = [ " << std::real(A) << " " << std::imag(A) - << " ] g = [ "<< std::real(me.coupling()) << " " << std::imag(me.coupling()) << " ]" ); + << " ] g = [ "<< std::real(me.coupling()) << " " << std::imag(me.coupling()) << " ] " + << me.decayTree.quasiCP() ); if( m_dbThis ) me.amp.debug( evt.address() ); - me.coupling.print(); + //me.coupling.print(); } else for ( auto& me : m_matrixElements ) @@ -335,7 +336,7 @@ void CoherentSum::printVal(const Event& evt) unsigned int address = mE.addressData; std::cout << mE.decayTree.decayDescriptor() << " = " << mE.coefficient << " x " << evt.getCache( address ) << " address = " << address << " " << mE( evt ) << std::endl; - if( mE.coupling.couplings.size() != 1 ){ + if( mE.coupling.size() != 1 ){ std::cout << "CouplingConstants: " << std::endl; mE.coupling.print(); std::cout << "================================" << std::endl; diff --git a/src/Expression.cpp b/src/Expression.cpp index 544bf5e111f..aaf947bf391 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -178,10 +178,10 @@ Expression AmpGen::operator>( const Expression& A, const Expression& B ) { retur Expression Expression::operator-() const { return Constant( -1. ) * m_expression; } -Expression Expression::operator+=( const Expression& other ) const { return *this + other ; } -Expression Expression::operator-=( const Expression& other ) const { return *this - other ; } -Expression Expression::operator*=( const Expression& other ) const { return *this * other ; } -Expression Expression::operator/=( const Expression& other ) const { return *this / other; } +Expression Expression::operator+=(const Expression& other) { *this = *this + other; return *this; } +Expression Expression::operator-=(const Expression& other) { *this = *this - other; return *this; } +Expression Expression::operator*=(const Expression& other) { *this = *this * other; return *this; } +Expression Expression::operator/=(const Expression& other) { *this = *this / other; return *this; } std::ostream& AmpGen::operator<<( std::ostream& os, const Expression& expression ) { return os << expression.to_string() ; } Expression::Expression( const double& value ) : m_expression( std::make_shared( value ) ) {} diff --git a/src/Lineshapes/Isotensor.cpp b/src/Lineshapes/Isotensor.cpp index 0d7030d7fa5..d2f2b0fa74d 100644 --- a/src/Lineshapes/Isotensor.cpp +++ b/src/Lineshapes/Isotensor.cpp @@ -1,11 +1,13 @@ #include #include +#include #include "AmpGen/Expression.h" #include "AmpGen/Factory.h" #include "AmpGen/Lineshapes.h" using namespace AmpGen; +using namespace std::complex_literals; DEFINE_LINESHAPE( Isotensor ) { @@ -23,8 +25,5 @@ DEFINE_LINESHAPE( Isotensor ) ADD_DEBUG( phaseShift, dbexpressions ); ADD_DEBUG( fcn::sqrt( s / 4 - mpi * mpi ), dbexpressions ); ADD_DEBUG( polyTerm, dbexpressions ); - Expression cos_shift = Cos( phaseShift ); - Expression sin_shift = Sin( phaseShift ); - Expression J = Constant(0,1); - return ( cos_shift + J*sin_shift - 1 ) * (-0.5 * J ); + return ( fcn::exp( 1i * phaseShift) - 1 ) / 2i; } diff --git a/src/MinuitExpression.cpp b/src/MinuitExpression.cpp index 9109155da38..424ada7db59 100644 --- a/src/MinuitExpression.cpp +++ b/src/MinuitExpression.cpp @@ -13,6 +13,11 @@ MinuitExpression::MinuitExpression( const std::vector& tokens, Minu { setName( tokens[0] ); m_expression = ExpressionParser::parse(tokens.begin() + 2 , tokens.end() , mps ); - m_isGood = true; fix(); } + +double MinuitExpression::mean() const { return std::real(getVal()); } +complex_t MinuitExpression::getVal() const { return m_expression(); } +MinuitExpression::operator double() const { return std::real(getVal()); } +MinuitExpression::~MinuitExpression() = default; + diff --git a/src/MinuitParameter.cpp b/src/MinuitParameter.cpp index 26ae2e5f1ba..3c2d5941e97 100644 --- a/src/MinuitParameter.cpp +++ b/src/MinuitParameter.cpp @@ -28,18 +28,18 @@ MinuitParameter::MinuitParameter( const std::string& name, const double& mean, c resetToInit(); } -Flag MinuitParameter::flag() const { return m_flag; } -double MinuitParameter::meanInit() const { return m_meanInit; } -double MinuitParameter::stepInit() const { return m_stepInit; } -double MinuitParameter::minInit() const { return m_minInit; } -double MinuitParameter::maxInit() const { return m_maxInit; } -double MinuitParameter::mean() const { return m_meanResult; } -double MinuitParameter::errPos() const { return m_errPosResult; } -double MinuitParameter::errNeg() const { return m_errNegResult; } -double MinuitParameter::err() const { return m_errResult; } -bool MinuitParameter::isFixed() const { return m_flag == Flag::Fix || m_flag == Flag::CompileTimeConstant; } -bool MinuitParameter::isFree() const { return m_flag == Flag::Free; } -const std::string& MinuitParameter::name() const { return m_name; } +Flag MinuitParameter::flag() const { return m_flag; } +double MinuitParameter::meanInit() const { return m_meanInit; } +double MinuitParameter::stepInit() const { return m_stepInit; } +double MinuitParameter::minInit() const { return m_minInit; } +double MinuitParameter::maxInit() const { return m_maxInit; } +double MinuitParameter::mean() const { return m_meanResult; } +double MinuitParameter::errPos() const { return m_errPosResult; } +double MinuitParameter::errNeg() const { return m_errNegResult; } +double MinuitParameter::err() const { return m_errResult; } +bool MinuitParameter::isFixed() const { return m_flag == Flag::Fix || m_flag == Flag::CompileTimeConstant; } +bool MinuitParameter::isFree() const { return m_flag == Flag::Free; } +const std::string& MinuitParameter::name() const { return m_name; } void MinuitParameter::fix() { m_flag = Flag::Fix; } void MinuitParameter::scaleStep( const double& sf ) @@ -83,7 +83,8 @@ void MinuitParameter::setLimits( const double& min, const double& max ) m_maxInit = max; } -std::ostream& AmpGen::operator<<( std::ostream& os, const MinuitParameter& par ){ +std::ostream& AmpGen::operator<<( std::ostream& os, const MinuitParameter& par ) +{ return os << std::left << std::setw(60) << par.name() << " = " << std::right << std::setw(12) << par.mean() << " ± " << std::left << std::setw(12) << par.stepInit() diff --git a/src/MinuitParameterSet.cpp b/src/MinuitParameterSet.cpp index 5040f6ede6e..2b519c01eb3 100644 --- a/src/MinuitParameterSet.cpp +++ b/src/MinuitParameterSet.cpp @@ -166,13 +166,7 @@ void MinuitParameterSet::tryAlias( const std::vector& line ) { if ( line.size() < 3 ) return; if ( line[1] == "=" ) { - MinuitExpression* expr = new MinuitExpression(line, this ); - if ( expr->isGood() ) { - addToEnd( expr ); - } else { - ERROR( "Expression is ill-formed: " << line[0] ); - delete expr; - } + addToEnd( new MinuitExpression(line, this) ); } } @@ -210,14 +204,14 @@ void MinuitParameterSet::resetToInit() void MinuitParameterSet::rename(const std::string& name, const std::string& new_name) { - auto it = at(name); + auto it = find(name); if( it == nullptr ){ ERROR("Parameter: " << name << " not found"); return; } if( name == new_name ) return; - if( at(new_name) != nullptr ){ - ERROR("New key for " << name << " = " << new_name << " already exists"); + if( find(new_name) != nullptr ){ + // ERROR("New key for " << name << " = " << new_name << " already exists"); return; } it->setName(new_name); diff --git a/src/Particle.cpp b/src/Particle.cpp index b51f3d8309a..2f2598762ca 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -112,6 +112,18 @@ Particle::Particle( const std::string& name, const unsigned int& index ) : Parti m_uniqueString = makeUniqueString(); } +bool Particle::isValidDecayDescriptor( const std::string& decayDescriptor ) +{ + size_t firstOpen = decayDescriptor.find("{"); + size_t open = std::count(decayDescriptor.begin(), decayDescriptor.end(), '{'); + size_t close = std::count(decayDescriptor.begin(), decayDescriptor.end(), '}'); + if( open == 0 || open != close || firstOpen == std::string::npos) return false; + std::string firstState = decayDescriptor.substr(0, firstOpen); + auto firstSquare = firstState.find("["); + if( firstSquare == std::string::npos ) return ParticleProperties::get( firstState, true ) != nullptr; + return ParticleProperties::get( firstState.substr(0, firstSquare), true ) != nullptr; +} + void Particle::parseModifier( const std::string& mod ) { if ( Lineshape::Factory::isLineshape( mod ) ) @@ -787,7 +799,10 @@ std::string Particle::decayDescriptor() const { return m_uniqueString ; } int Particle::quasiCP() const { - int prod = m_props->C() == 0 ? 1 : m_props->C(); + if( m_daughters.size() == 1 ) return m_daughters[0]->quasiCP(); + int prod = m_props->C() == 0 ? 1 : m_props->C() ; + if( m_daughters.size() == 0 && m_props->C() != 0 ) + prod *= std::pow( -1, 0.5 * double(m_props->twoSpin()) ); prod *= ( m_orbital % 2 == 0 ? 1 : -1 ); for( auto& d : m_daughters ) prod *= d->quasiCP() ; return prod; diff --git a/src/TreePhaseSpace.cpp b/src/TreePhaseSpace.cpp new file mode 100644 index 00000000000..536a41200f4 --- /dev/null +++ b/src/TreePhaseSpace.cpp @@ -0,0 +1,267 @@ +#include "AmpGen/TreePhaseSpace.h" +#include "AmpGen/MsgService.h" +#include "AmpGen/ParticleProperties.h" +#include "AmpGen/Utilities.h" +#include "TRandom.h" +#include "TRandom3.h" +#include +#include + +using namespace AmpGen; + +TreePhaseSpace::TreePhaseSpace(const Particle& decayChain, const EventType& type, TRandom* rndm) : + m_rand(rndm == nullptr ? (TRandom3*)gRandom : (TRandom3*)rndm), + m_type(type), + m_gen(1) +{ + auto orderings = decayChain.identicalDaughterOrderings(); + for( auto& ordering : orderings ) + { + Particle p = decayChain; + p.setOrdering(ordering); + m_top.push_back( Vertex::make( p) ); + m_weights.push_back(1); + } + m_dice = std::discrete_distribution<>(m_weights.begin(), m_weights.end()); + setRandom(m_rand); +} + +TreePhaseSpace::TreePhaseSpace(const std::vector& decayChains, const EventType& type, TRandom* rndm) : + m_rand(rndm == nullptr ? (TRandom3*)gRandom : (TRandom3*)rndm), + m_type(type), + m_gen(1) +{ + for( auto& decayChain : decayChains ) + { + auto orderings = decayChain.identicalDaughterOrderings(); + for( auto& ordering : orderings ) + { + Particle p = decayChain; + p.setOrdering(ordering); + m_top.push_back( Vertex::make(p) ); + m_weights.push_back(1); + } + setRandom(rndm); + } + m_dice = std::discrete_distribution<>(m_weights.begin(), m_weights.end()); +} + +Event TreePhaseSpace::makeEvent( const unsigned& cacheSize ) +{ + double w = 0; + unsigned j = 0 ; + do { + j = m_dice(m_gen); + m_top[j].generate(); + w = m_top[j].weight(); + } while( w < m_rand->Rndm() ); + auto event = m_top[j].event(m_type.size(), cacheSize); + event.setGenPdf(genPdf(event)); + return event; +} + +double rho( const double& s, const double& s1, const double& s2) +{ + return sqrt( 1 - 2 * (s1+s2)/s + (s1-s2)*(s1-s2) /(s*s) ); +} + +TreePhaseSpace::Vertex::Vertex(const Particle& particle, const double& min) + : particle(particle) + , min(min) + , max(min) + , isStable(true) + , isBW(particle.lineshape() == "BW") + , index(particle.index()) + , bwMass(particle.props()->mass()) + , bwWidth(particle.props()->width()) +{ + if( index != 999 ) indices = {index}; + phiMin = atan((min*min - bwMass*bwMass)/(bwMass*bwWidth)); + phiMax = atan((min*min - bwMass*bwMass)/(bwMass*bwWidth)); +// if( isBW ) INFO( min << " ΔΦ= " << phiMax - phiMin << " " << bwMass << " " << bwWidth << " E= [" << max <<", " << min*min << "]" ); +} + + +TreePhaseSpace::Vertex::Vertex(const Particle& particle, const double& min, const double& max, const bool& isStable ) + : particle(particle) + , min(min) + , max(max) + , isStable(isStable) + , isBW(particle.lineshape() == "BW") + , index(particle.index()) + , bwMass(particle.props()->mass()) + , bwWidth(particle.props()->width()) +{ + if( index != 999 ) indices = {index}; + phiMin = atan((min*min - bwMass*bwMass)/(bwMass*bwWidth)); + phiMax = atan((max*max - bwMass*bwMass)/(bwMass*bwWidth)); +// if( isBW ) INFO( min << " ΔΦ= " << phiMax - phiMin << " " << bwMass << " " << bwWidth << " E= [" << max*max <<", " << min*min << "]" ); +} + +double TreePhaseSpace::Vertex::p() const +{ + return 0.5 * sqrt( s - 2 * (left->s+right->s) + (left->s-right->s)*(left->s-right->s)/s ); +} + +double TreePhaseSpace::Vertex::genBW() const +{ + return isBW ? bwMass * bwMass + bwMass * bwWidth * tan( ( phiMax - phiMin ) * rand->Rndm() + phiMin ) : (max*max-min*min)*rand->Rndm() + min*min; +} + +double TreePhaseSpace::Vertex::BW(const double& si) const +{ + double m = bwMass; + double w = bwWidth; + double N = m * w / (phiMax - phiMin); + return isBW ? N / ( (si - m*m)*(si-m*m) + m*m*w*w) : 1./(max*max - min*min); +} + +double TreePhaseSpace::Vertex::weight() const +{ + if( left == nullptr || right == nullptr ) return 1.0; + double w = sqrt(s) - sqrt(left->s) - sqrt(right->s) > 0; + if( w == 0 ) return 0; + w *= rho(s, left->s, right->s) / rhoMax; + w *= left -> weight(); + w *= right -> weight(); + return w; +} + +double TreePhaseSpace::Vertex::maxWeight() const +{ + double w = 1.0; + if( left == nullptr || right == nullptr ) return 1.0; + w *= rhoMax; + w *= left -> maxWeight(); + w *= right -> maxWeight(); + return w; +} + +double TreePhaseSpace::Vertex::genPdf(const Event& event) const +{ + if( left == nullptr || right == nullptr ) return 1; + double dp = left->genPdf(event) * right->genPdf(event); + return dp * ( isStable ? 1 : BW( event.s(indices) ) ); +} + +void TreePhaseSpace::Vertex::generate() +{ + s = isStable ? min*min : genBW(); + if( left != nullptr ) left->generate(); + if( right != nullptr ) right->generate(); +} + +void TreePhaseSpace::Vertex::print(const unsigned& offset) const +{ + double rhoc = ( left != nullptr && right != nullptr ? rho(s,left->s,right->s) : rhoMax ); + if( isStable ) INFO( std::string(offset,' ') << particle.name() << " [" << vectorToString(indices, ", ") << "] → [" << min << "], ϱ' = " << rhoMax << ", s = " << s << ", ϱ = " << rhoc << " w = " << weight() ); + else INFO( std::string(offset,' ') << particle.name() << " [" << vectorToString(indices, ", ") << "] → [" << min << ", " << max << "] ϱ' =" << rhoMax << ", s = " << s << ", ϱ = " << rhoc << " w = " << weight() ); + if( left != nullptr ) left -> print( offset + 4 ); + if( right != nullptr ) right -> print( offset + 4 ); +} + +void TreePhaseSpace::Vertex::place(Event& event) +{ + if( index != 999 ){ + event[4*index+0] = mom[0]; + event[4*index+1] = mom[1]; + event[4*index+2] = mom[2]; + event[4*index+3] = mom[3]; + } + if( left != nullptr ) left->place(event); + if( right != nullptr ) right->place(event); +} + +Event TreePhaseSpace::Vertex::event(const unsigned& eventSize, const unsigned& cacheSize) +{ + Event output(4 * eventSize, cacheSize); + generate_full_event_description( TLorentzVector(0,0,0,sqrt(s)) ); + place(output); + return output; +} + +void TreePhaseSpace::Vertex::generate_full_event_description(const TLorentzVector& parentVector) +{ + mom = parentVector; + double cosTheta = 2 * rand->Rndm() - 1; + double sinTheta = sqrt( 1 - cosTheta * cosTheta ); + double angY = 2 * M_PI * rand->Rndm(); + double cosPhi = cos(angY); + double sinPhi = sin(angY); + if( left == nullptr || right == nullptr ) return; + double pf = p(); + TLorentzVector lvThisFrame( pf*sinTheta*cosPhi, pf*sinTheta*sinPhi, pf*cosTheta, sqrt(left->s + pf*pf) ); + TLorentzVector rvThisFrame( -pf*sinTheta*cosPhi, -pf*sinTheta*sinPhi, -pf*cosTheta, sqrt(right->s + pf*pf) ); + lvThisFrame.Boost( parentVector.BoostVector() ); + rvThisFrame.Boost( parentVector.BoostVector() ); + left -> generate_full_event_description(lvThisFrame); + right -> generate_full_event_description(rvThisFrame); +} + +void TreePhaseSpace::Vertex::setRhoMax() +{ + rhoMax = rho(max*max, left->min * left->min, right->min * right->min ); + weightMax = maxWeight(); +} + +TreePhaseSpace::Vertex TreePhaseSpace::Vertex::make(const Particle& particle, TreePhaseSpace::Vertex* parent) +{ + auto decayProducts = particle.daughters(); + auto threshold = [](const Particle& particle) + { + auto d1 = particle.getFinalStateParticles(); + if( d1.size() == 0) return particle.mass(); + return std::accumulate(d1.begin(), d1.end(), 0., [](double acc, auto& p){ return acc + p->mass(); } ); + }; + if( decayProducts.size() == 1 ) return TreePhaseSpace::Vertex::make(*decayProducts[0], parent); + if( decayProducts.size() == 2 ) + { + TreePhaseSpace::Vertex vtx = (parent == nullptr) ? TreePhaseSpace::Vertex(particle, particle.mass(), particle.mass(), true) : TreePhaseSpace::Vertex(); + parent = ( parent == nullptr ) ? &vtx : parent; + + auto min_mass_1 = threshold(*decayProducts[0]); + auto min_mass_2 = threshold(*decayProducts[1]); + auto max_mass_1 = decayProducts[0]->isStable() ? min_mass_1 : parent->max - min_mass_2; + auto max_mass_2 = decayProducts[1]->isStable() ? min_mass_2 : parent->max - min_mass_1; + parent->left = std::make_shared(*decayProducts[0], min_mass_1, max_mass_1, decayProducts[0]->isStable() ); + parent->right = std::make_shared(*decayProducts[1], min_mass_2, max_mass_2, decayProducts[1]->isStable() ); + TreePhaseSpace::Vertex::make(*decayProducts[0], parent->left.get()); + TreePhaseSpace::Vertex::make(*decayProducts[1], parent->right.get()); + for( auto& index : parent->left ->indices ) parent->indices.push_back(index); + for( auto& index : parent->right->indices ) parent->indices.push_back(index); + parent->setRhoMax(); + return *parent; + } + return TreePhaseSpace::Vertex(); +} + +void TreePhaseSpace::setRandom( TRandom* rand ) +{ + m_rand = (TRandom3*)rand; + for( auto& channel : m_top ) channel.setRandom((TRandom3*)rand); +} + +void TreePhaseSpace::Vertex::setRandom( TRandom3* rnd ) +{ + rand = rnd; + if( left != nullptr ) left->setRandom(rnd); + if( right != nullptr ) right->setRandom(rnd); +} + +EventType TreePhaseSpace::eventType() const +{ + return m_type; +} + +double TreePhaseSpace::genPdf(const Event& event) const +{ + double genPdf = 0; + for( auto& channel : m_top ) genPdf += channel.genPdf(event) / channel.weightMax; // / channel->w; + return genPdf; +} + +size_t TreePhaseSpace::size() const +{ + return m_top.size(); +} + diff --git a/src/Utilities.cpp b/src/Utilities.cpp index 6bd5d6e3a37..66e359d3546 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -183,8 +183,13 @@ unsigned int AmpGen::editDistance( const std::string& s1, const std::string& s2 std::string AmpGen::round( const double& number, const unsigned int& nsf ) { double value = std::round(number * pow(10, nsf)) / pow(10, nsf); - auto r = mysprintf( ( "%." + std::to_string(nsf) + "f" ).c_str(), value ); - return r.substr(0,r.size()-1); + if( nsf != 0 ){ + auto r = mysprintf( ( "%." + std::to_string(nsf) + "f" ).c_str(), value ); + return r.substr(0,r.size()-1); + } + else { + return std::to_string( (int)value); + } } std::string AmpGen::numberWithError( const double& number, const double& error, const unsigned int& nDigits ) diff --git a/test/test_AmplitudeRules.cpp b/test/test_AmplitudeRules.cpp index eac040ba354..08a704eb007 100644 --- a/test/test_AmplitudeRules.cpp +++ b/test/test_AmplitudeRules.cpp @@ -16,7 +16,7 @@ BOOST_AUTO_TEST_CASE( test_AmplitudeRule ) { MinuitParameter re = MinuitParameter("D0{K*(892)bar0{K-,pi+},pi0}_Re", Flag::Free,1.,0.); MinuitParameter im = MinuitParameter("D0{K*(892)bar0{K-,pi+},pi0}_Im", Flag::Free,0.,0.); - AmplitudeRule test(&re,&im); + Coupling test(&re,&im); BOOST_CHECK( test.name() == "D0{K*(892)bar0{K-,pi+},pi0}" ); BOOST_CHECK( test.head() == "D0"); From de722a115a3e2a4299481227a1f51677ab435a23 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 24 Nov 2019 19:41:04 +0100 Subject: [PATCH 108/250] improve CP conjugation logic, add a couple of additional vertices --- AmpGen/ASTResolver.h | 3 + AmpGen/Expression.h | 2 +- AmpGen/Generator.h | 35 +++++--- AmpGen/Minimiser.h | 1 - AmpGen/MinuitParameterSet.h | 2 +- AmpGen/Particle.h | 13 +-- AmpGen/PhaseSpace.h | 1 + AmpGen/RecursivePhaseSpace.h | 1 + AmpGen/Tensor.h | 4 +- AmpGen/TreePhaseSpace.h | 16 ++-- AmpGen/Utilities.h | 1 + AmpGen/Vertex.h | 6 ++ apps/ConvertToSourceCode.cpp | 4 +- apps/Debugger.cpp | 60 +++++++++++--- apps/Generator.cpp | 55 ++++++++++++- doc/release.notes | 2 + examples/QcGenerator.cpp | 2 +- options/MintDalitzSpecialParticles.csv | 58 +++++++------- options/mass_width.csv | 52 ++++++------ src/CoherentSum.cpp | 4 +- src/EventType.cpp | 6 +- src/Minimiser.cpp | 14 ++++ src/MinuitParameterSet.cpp | 14 ++-- src/Particle.cpp | 107 +++++++++++++------------ src/ParticleProperties.cpp | 2 +- src/TreePhaseSpace.cpp | 71 ++++++++++------ src/Utilities.cpp | 7 ++ src/Vertex.cpp | 26 +++++- src/Wigner.cpp | 1 - 29 files changed, 380 insertions(+), 190 deletions(-) diff --git a/AmpGen/ASTResolver.h b/AmpGen/ASTResolver.h index 95287ad207b..fcfe3297fc0 100644 --- a/AmpGen/ASTResolver.h +++ b/AmpGen/ASTResolver.h @@ -48,7 +48,10 @@ namespace AmpGen { void addResolvedParameter(const IExpression* param, const std::string& thing); void addResolvedParameter(const IExpression* param, const size_t& address, const size_t& arg=0); std::string resolvedParameter( const IExpression* param ) const; + void clear(); + + std::map parameters() const { return m_resolvedParameters; } private: std::map m_resolvedParameters; /// Map of parameters that have been resolved std::map> m_cacheFunctions; /// Container of functions for calculating function cache diff --git a/AmpGen/Expression.h b/AmpGen/Expression.h index 2ffaeca166b..9c44737404b 100644 --- a/AmpGen/Expression.h +++ b/AmpGen/Expression.h @@ -178,7 +178,7 @@ namespace AmpGen const bool& resolved = false); std::string to_string(const ASTResolver* resolver = nullptr) const override; void resolve( ASTResolver& resolver ) const override; - operator Expression() const; + virtual operator Expression() const; complex_t operator()() const override { return complex_t( m_defaultValue, 0 ); } std::string name() const { return m_name; } const double& defaultValue() const { return m_defaultValue ; } diff --git a/AmpGen/Generator.h b/AmpGen/Generator.h index 0b6f1ed4ae6..761e954e4bb 100644 --- a/AmpGen/Generator.h +++ b/AmpGen/Generator.h @@ -63,12 +63,14 @@ namespace AmpGen ERROR( "Random generator not set!" ); return; } - double normalisationConstant = m_normalise ? 0 : 1; - auto size0 = list.size(); - auto tStartTotal = std::chrono::high_resolution_clock::now(); + double maxProb = m_normalise ? 0 : 1; + auto size0 = list.size(); + auto tStartTotal = std::chrono::high_resolution_clock::now(); pdf.reset( true ); ProgressBar pb(60, trimmedString(__PRETTY_FUNCTION__) ); ProfileClock t_phsp, t_eval, t_acceptReject; + std::vector efficiencyReport(m_generatorBlock,false); + while ( list.size() - size0 < N ) { EventList mc( m_eventType ); t_phsp.start(); @@ -78,30 +80,38 @@ namespace AmpGen pdf.setEvents( mc ); pdf.prepare(); t_eval.stop(); - if ( normalisationConstant == 0 ) { + if ( maxProb == 0 ) { double max = 0; for ( auto& evt : mc ) { - double value = pdf.prob_unnormalised( evt ) / evt.genPdf(); + double value = pdf.prob_unnormalised(evt) / evt.genPdf(); if ( value > max ) max = value; } - normalisationConstant = max * 1.5; - INFO( "Setting normalisation constant = " << normalisationConstant ); + maxProb = max * 1.5; + INFO( "Setting normalisation constant = " << maxProb ); } auto previousSize = list.size(); t_acceptReject.start(); #ifdef _OPENMP #pragma omp parallel for #endif - for ( size_t i=0;i< mc.size(); ++i ) mc[i].setGenPdf(pdf.prob_unnormalised(mc[i]) / mc[i].genPdf()); + for ( size_t i=0; i < mc.size(); ++i ) + mc[i].setGenPdf(pdf.prob_unnormalised(mc[i]) / mc[i].genPdf()); - for( auto& evt : mc ){ - if ( evt.genPdf() > normalisationConstant ) { + for( size_t i=0; i != mc.size(); ++i ) + { + auto& evt = mc[i]; + if ( evt.genPdf() > maxProb ) { std::cout << std::endl; - WARNING( "PDF value exceeds norm value: " << evt.genPdf() << " > " << normalisationConstant ); + WARNING( "PDF value exceeds norm value: " << evt.genPdf() << " > " << maxProb ); } - if ( evt.genPdf() > normalisationConstant * m_rnd->Rndm() ) list.push_back( evt ); + if ( evt.genPdf() > maxProb * m_rnd->Rndm() ){ + list.push_back(evt); + efficiencyReport[i] = true; + } + else efficiencyReport[i] = false; if ( list.size() - size0 == N ) break; } + m_gps.provideEfficiencyReport( efficiencyReport ); t_acceptReject.stop(); double time = std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); double efficiency = 100. * ( list.size() - previousSize ) / (double)m_generatorBlock; @@ -110,6 +120,7 @@ namespace AmpGen ERROR( "No events generated, PDF: " << typeof() << " is likely to be malformed" ); break; } +// maxProb = 0; } pb.finish(); double time = std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); diff --git a/AmpGen/Minimiser.h b/AmpGen/Minimiser.h index 66a6580f682..9400f3c3c99 100644 --- a/AmpGen/Minimiser.h +++ b/AmpGen/Minimiser.h @@ -80,7 +80,6 @@ namespace AmpGen MinuitParameterSet* parSet() const; int status() const; ROOT::Minuit2::Minuit2Minimizer* minimiserInternal(); - private: MinuitParameterSet* m_parSet = {nullptr}; std::function m_theFunction; diff --git a/AmpGen/MinuitParameterSet.h b/AmpGen/MinuitParameterSet.h index e72c92ce63d..e4aa9bb8187 100644 --- a/AmpGen/MinuitParameterSet.h +++ b/AmpGen/MinuitParameterSet.h @@ -38,7 +38,7 @@ namespace AmpGen void print( std::ostream& os = std::cout ) const; void printVariable( std::ostream& os = std::cout ) const; void set( const MinuitParameterSet& mps ); - void rename(const std::string& name, const std::string& new_name); + bool rename(const std::string& name, const std::string& new_name); unsigned int size() const; const_iterator cbegin() const; diff --git a/AmpGen/Particle.h b/AmpGen/Particle.h index 1318d90df42..030315efc54 100644 --- a/AmpGen/Particle.h +++ b/AmpGen/Particle.h @@ -115,6 +115,10 @@ namespace AmpGen /// (Quasi) Constructor that returns the (quasi)CP conjugated amplitude. The full behaviour of the amplitude is made more complicated by the ordering convention. Particle conj(bool invertHead = true, bool reorder = true); + /// CP conjugate this particle // + + void conjThis(); + static bool isValidDecayDescriptor( const std::string& decayDescriptor ); /// Set the orbital quantum number 'L' for this decay. void setOrbital( const unsigned int& orbital ); @@ -172,9 +176,8 @@ namespace AmpGen int finalStateParity() const; ///< Returns the parity of the final state of this particle int polState() const; ///< Returns the polarisation state, i.e. twice the projection of the spin along the quantisation axis, of this particle. - int quasiCP() const; ///< Returns the ``quasi'' CP Quantum number for this decay, see the Particle + int CP() const; ///< Returns the CP of this decay. int C() const; ///< Returns the C quantum number for this decay - double mass() const; ///< Returns the (PDG) mass of the particle double spin() const; ///< Returns the spin of the particle double S() const; ///< Returns the spin configuration of the decay products of the particle @@ -191,7 +194,6 @@ namespace AmpGen unsigned originalIndex() const; ///< Returns the original index of the particle std::string name() const; ///< Name of the decaying particle. std::string lineshape() const; ///< Name of the propagator to use for the decay of this particle. - std::string vertexName() const; ///< Name of the (spin)vertex to use for the decay of this particle std::string uniqueString() const; ///< Returns the unique string (i.e. decay descriptor) that identifies this decay, which can be parsed to generate the decay tree. std::string decayDescriptor() const;///< Returns the unique string (i.e. decay descriptor) that identifies this decay, which can be parsed to generate the decay tree. @@ -267,6 +269,7 @@ namespace AmpGen }; /// matches Check the matching between two decay chains, according to the MatchState enum. unsigned int matches( const Particle& other ) const; + std::string makeUniqueString(); ///< Generate the decay descriptor for this decay. private: const ParticleProperties* m_props = {nullptr}; ///< Particle Properties from the PDG std::string m_name = {""}; ///< Name of the particle @@ -287,11 +290,11 @@ namespace AmpGen std::string m_spinFormalism = {""}; ///< Spin formalism to use for this particle (global) std::string m_spinBasis = {""}; ///< Basis to use for external polarisations (global) std::string m_defaultModifier = {""}; ///< Default Modifier to use (global) - + bool m_cpOrderConvention = {false}; ///< Use modified particle ordering convention that should be more robust with respect to CP conjugation + void pdgLookup(); ///< Lookup information from the PDG database (using ParticlePropertiesList) bool hasModifier( const std::string& modifier ) const; ///< Check if this particle has a given modifier std::string modifierString() const; ///< Re-generate modifier string used to create particle - std::string makeUniqueString(); ///< Generate the decay descriptor for this decay. void sortDaughters(); ///< Recursively order the particle's decay products. }; std::ostream& operator<<( std::ostream& os, const Particle& particle ); diff --git a/AmpGen/PhaseSpace.h b/AmpGen/PhaseSpace.h index a00b31f9cf1..7abf796b106 100644 --- a/AmpGen/PhaseSpace.h +++ b/AmpGen/PhaseSpace.h @@ -32,6 +32,7 @@ namespace AmpGen Event makeEvent( const size_t& cacheSize = 0 ); ///< Make an event in this phase space. EventType eventType() const; ///< Returns the EventType that this phase space is generating + void provideEfficiencyReport(const std::vector& report){} private: size_t m_nt = {0}; ///< Number of particles in the final state double m_mass[18] = {0}; ///< Masses of particles in the final state diff --git a/AmpGen/RecursivePhaseSpace.h b/AmpGen/RecursivePhaseSpace.h index 0d63cfa3190..73cb08f8bbe 100644 --- a/AmpGen/RecursivePhaseSpace.h +++ b/AmpGen/RecursivePhaseSpace.h @@ -51,6 +51,7 @@ namespace AmpGen size_t size() const; EventType eventType() const ; + void provideEfficiencyReport(const std::vector& report){} private: PhaseSpace m_phsp; unsigned m_totalSize = {0}; diff --git a/AmpGen/Tensor.h b/AmpGen/Tensor.h index 168970d485b..c0b656edcc8 100644 --- a/AmpGen/Tensor.h +++ b/AmpGen/Tensor.h @@ -15,8 +15,8 @@ #include "AmpGen/Types.h" #define ADD_DEBUG_TENSOR( X, Y ) \ - if ( Y != nullptr ) for( unsigned i = 0 ; i < X.size(); ++i ) \ - Y->emplace_back( std::string(#X) + Tensor::coordinates_to_string( X.coords(i) ) , X[i] ); + if ( Y != nullptr ) for( unsigned i = 0 ; i < Tensor(X).size(); ++i ) \ + Y->emplace_back( std::string(#X) + Tensor::coordinates_to_string( Tensor(X).coords(i) ) , Tensor(X)[i] ); #define ADD_DEBUG_TENSOR_NAMED( X, Y, Z ) \ if ( Y != nullptr ) for( unsigned i = 0 ; i < X.size(); ++i ) \ diff --git a/AmpGen/TreePhaseSpace.h b/AmpGen/TreePhaseSpace.h index e3aa8c1186a..f9c3f33922a 100644 --- a/AmpGen/TreePhaseSpace.h +++ b/AmpGen/TreePhaseSpace.h @@ -52,7 +52,7 @@ namespace AmpGen void print(const unsigned& offset = 0) const; void place(Event& event); Event event(const unsigned& eventSize, const unsigned& cacheSize=0); - void generate_full_event_description(const TLorentzVector& parentVector); + void generateFullEvent(); void setRhoMax(); void setRandom(TRandom3* rnd); static Vertex make(const Particle& particle, Vertex* parent = nullptr); @@ -88,13 +88,15 @@ namespace AmpGen double genPdf( const Event& event) const ; const Vertex& operator[](const unsigned i) const { return m_top[i]; } + void provideEfficiencyReport(const std::vector& report); private: - std::vector m_top; - TRandom3* m_rand = {nullptr}; - EventType m_type; ///< EventType to generate - std::discrete_distribution<> m_dice; ///< - std::vector m_weights; - std::mt19937 m_gen; + std::vector m_top; + TRandom3* m_rand = {nullptr}; + EventType m_type; ///< EventType to generate + std::discrete_distribution<> m_dice; ///< + std::vector m_weights; + std::vector m_generatorRecord; + std::mt19937 m_gen; }; } // namespace AmpGen diff --git a/AmpGen/Utilities.h b/AmpGen/Utilities.h index 63d063fafc4..985bd3fdd71 100644 --- a/AmpGen/Utilities.h +++ b/AmpGen/Utilities.h @@ -66,6 +66,7 @@ namespace AmpGen { size_t find_next_of( const std::string& input, const std::vector& patterns, const size_t& begin = 0 ); std::string replaceAll( const std::string& input, const std::string& toReplace, const std::string& replaceWith ); + std::string replaceAll( const std::string& input, const std::vector>& rules ); unsigned int FNV1a_hash( const std::string& toHash ); diff --git a/AmpGen/Vertex.h b/AmpGen/Vertex.h index 5ea2b76fdb7..ba62cb69cf6 100644 --- a/AmpGen/Vertex.h +++ b/AmpGen/Vertex.h @@ -138,6 +138,12 @@ namespace AmpGen DECLARE_VERTEX( f_Vf_P2 ); DECLARE_VERTEX( f_Vf_P3 ); + DECLARE_VERTEX( f_fS_SL ); + DECLARE_VERTEX( f_fS_SR ); + + DECLARE_VERTEX( f_Vf_SL ); + DECLARE_VERTEX( f_Vf_SR ); + DECLARE_VERTEX( f_Vf_D ); DECLARE_VERTEX( f_Vf_D1 ); diff --git a/apps/ConvertToSourceCode.cpp b/apps/ConvertToSourceCode.cpp index 954e9290f84..60019f56a05 100644 --- a/apps/ConvertToSourceCode.cpp +++ b/apps/ConvertToSourceCode.cpp @@ -87,8 +87,8 @@ void invert( MinuitParameter* param, MinuitParameterSet& mps ) std::string name = tokens[0]; if ( reOrIm == "Re" || reOrIm == "Im" ){ Particle test = Particle(name).conj(); - if( cartOrPolar == "polar" ) sgn = reOrIm == "Re" ? test.quasiCP() : 1; - if( cartOrPolar == "cartesian" ) sgn = test.quasiCP(); + if( cartOrPolar == "polar" ) sgn = reOrIm == "Re" ? test.CP() : 1; + if( cartOrPolar == "cartesian" ) sgn = test.CP(); new_name = test.uniqueString() +"_"+reOrIm; } else if( tokens.size() == 2 ) { diff --git a/apps/Debugger.cpp b/apps/Debugger.cpp index 2257f1a54a8..6e3b73a58fa 100644 --- a/apps/Debugger.cpp +++ b/apps/Debugger.cpp @@ -52,7 +52,6 @@ void invert( MinuitParameter* param, MinuitParameterSet& mps ) std::string new_name = name; int sgn = 1; std::string cartOrPolar = NamedParameter("CouplingConstant::Coordinates" ,"cartesian"); - if( name.find("::") != std::string::npos ){ pos = name.find("::"); auto props = AmpGen::ParticlePropertiesList::get( name.substr(0,pos), true ); @@ -64,8 +63,8 @@ void invert( MinuitParameter* param, MinuitParameterSet& mps ) std::string name = tokens[0]; if ( reOrIm == "Re" || reOrIm == "Im" ){ Particle test = Particle(name).conj(); - if( cartOrPolar == "polar" ) sgn = reOrIm == "Re" ? test.quasiCP() : 1; - if( cartOrPolar == "cartesian" ) sgn = test.quasiCP(); + if( cartOrPolar == "polar" ) sgn = reOrIm == "Re" ? test.CP() : 1; + if( cartOrPolar == "cartesian" ) sgn = test.CP(); new_name = test.uniqueString() +"_"+reOrIm; } else if( tokens.size() == 2 ) { @@ -73,12 +72,48 @@ void invert( MinuitParameter* param, MinuitParameterSet& mps ) if( props != 0 ) new_name = props->anti().name() + "_" + tokens[1]; } } - //INFO( param->name() << " " << sgn ); - mps.rename( param->name(), new_name ); - if( sgn == -1 ) param->setCurrentFitVal( -1 * param->mean() ); + if( mps.rename( param->name(), new_name ) && sgn == -1 ) + param->setCurrentFitVal( -1 * param->mean() ); } +void add_CP_conjugate( MinuitParameterSet& mps ) +{ + std::vector tmp; + std::string cartOrPolar = NamedParameter("CouplingConstant::Coordinates" ,"cartesian"); + for( auto& param : mps ){ + const std::string name = param->name(); + size_t pos=0; + std::string new_name = name; + int sgn=1; + if( name.find("::") != std::string::npos ){ + pos = name.find("::"); + auto props = AmpGen::ParticlePropertiesList::get( name.substr(0,pos), true ); + if( props != 0 ) new_name = props->anti().name() + name.substr(pos); + } + else { + auto tokens=split(name,'_'); + std::string reOrIm = *tokens.rbegin(); + std::string name = tokens[0]; + if ( reOrIm == "Re" || reOrIm == "Im" ){ + Particle test = Particle(name).conj(); + if( cartOrPolar == "polar" ) sgn = reOrIm == "Re" ? test.CP() : 1; + if( cartOrPolar == "cartesian" ) sgn = test.CP(); + new_name = test.uniqueString() +"_"+reOrIm; + } + else if( tokens.size() == 2 ) { + auto props = AmpGen::ParticlePropertiesList::get( name ); + if( props != 0 ) new_name = props->anti().name() + "_" + tokens[1]; + } + } + if( mps.find( new_name ) == nullptr ) tmp.push_back( new MinuitParameter(new_name, Flag::Free, sgn * param->mean(), param->err(), 0, 0)); + } + for( auto& p : tmp ){ + INFO("Adding parameter: " << p->name() ); + mps.add( p ); + } +} +/* template void print( const Event& event, const MatrixElements& matrixElements, bool verbose ) { for ( auto& mE : matrixElements ) { @@ -91,6 +126,7 @@ template void print( const Event& event, const MatrixElem } } } +*/ template < class FCN > void debug( FCN& sig, EventList& accepted, bool verbose, TRandom3* rndm, MinuitParameterSet& mps ){ INFO("Debugging: "); @@ -98,7 +134,7 @@ template < class FCN > void debug( FCN& sig, EventList& accepted, bool verbose, sig.prepare(); sig.debug( accepted[0] ); accepted[0].print(); - if( verbose ) print( accepted[0], sig.matrixElements(), verbose ); +// if( verbose ) print( accepted[0], sig.matrixElements(), verbose ); invertParity(accepted[0], accepted.eventType().size() ); accepted[0].print(); sig.reset(); @@ -122,9 +158,11 @@ int main( int argc, char** argv ) AmpGen::MinuitParameterSet MPS; MPS.loadFromStream(); - if ( NamedParameter( "conj", false ) == true ) { - eventType = eventType.conj(false); - for ( auto& param : MPS ) invert( param, MPS ); + if ( NamedParameter( "conj", false ) == true ) + { + eventType = eventType.conj(); + INFO( eventType ); + add_CP_conjugate(MPS); } INFO( "EventType = " << eventType ); @@ -154,7 +192,7 @@ int main( int argc, char** argv ) { CoherentSum sig(eventType, MPS); debug(sig, accepted, verbose, rndm, MPS); - print(accepted[0], sig.matrixElements() , false); + // print(accepted[0], sig.matrixElements() , false); INFO( "A(x) = " << sig.getValNoCache( accepted[0] ) ); } else { diff --git a/apps/Generator.cpp b/apps/Generator.cpp index afc562e898b..faa876dbeb0 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -28,11 +28,44 @@ #include "AmpGen/OptionsParser.h" #include "AmpGen/TreePhaseSpace.h" #include "AmpGen/enum.h" +#include "AmpGen/ParticlePropertiesList.h" using namespace AmpGen; namespace AmpGen { make_enum(generatorType, CoherentSum, PolarisedSum, FixedLib, RGenerator, TreePhaseSpace) } +void invert( MinuitParameter* param, MinuitParameterSet& mps ) +{ + const std::string name = param->name(); + size_t pos = 0; + std::string new_name = name; + int sgn = 1; + std::string cartOrPolar = NamedParameter("CouplingConstant::Coordinates" ,"cartesian"); + + if( name.find("::") != std::string::npos ){ + pos = name.find("::"); + auto props = ParticlePropertiesList::get( name.substr(0,pos), true ); + if( props != 0 ) new_name = props->anti().name() + name.substr(pos); + } + else { + auto tokens=split(name,'_'); + std::string reOrIm = *tokens.rbegin(); + std::string name = tokens[0]; + if ( reOrIm == "Re" || reOrIm == "Im" ){ + Particle test = Particle(name).conj(); + if( cartOrPolar == "polar" ) sgn = reOrIm == "Re" ? test.CP() : 1; + if( cartOrPolar == "cartesian" ) sgn = test.CP(); + new_name = test.uniqueString() +"_"+reOrIm; + } + else if( tokens.size() == 2 ) { + auto props = ParticlePropertiesList::get( name ); + if( props != 0 ) new_name = props->anti().name() + "_" + tokens[1]; + } + } + if( mps.rename( param->name(), new_name ) && sgn == -1 ) + param->setCurrentFitVal( -1 * param->mean() ); +} + struct FixedLibPDF { void* lib = {nullptr}; AmpGen::DynamicFCN PDF; @@ -97,8 +130,24 @@ int main( int argc, char** argv ) MinuitParameterSet MPS; MPS.loadFromStream(); - EventType eventType( NamedParameter( "EventType" , "", "EventType to generate, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(), - NamedParameter( "GenerateTimeDependent", false , "Flag to include possible time dependence of the amplitude") ); + EventType eventType; + std::string decay = NamedParameter("Decay","","Single decay written on the command line"); + if( decay != "" ) + { + Particle p(decay); + eventType = p.eventType(); + MPS.add(p.decayDescriptor()+"_Re", Flag::Fix, 1., 0); + MPS.add(p.decayDescriptor()+"_Im", Flag::Fix, 0., 0); + } + else eventType = EventType( NamedParameter( "EventType" , "", "EventType to generate, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(), + NamedParameter( "GenerateTimeDependent", false , "Flag to include possible time dependence of the amplitude") ); + + if ( NamedParameter( "conj", false ) == true ) { + eventType = eventType.conj(); + INFO( eventType ); + for ( auto& param : MPS ) invert( param, MPS ); + } + INFO("Generating time-dependence? " << eventType.isTimeDependent() ); EventList accepted( eventType ); @@ -122,7 +171,7 @@ int main( int argc, char** argv ) signalGenerator.fillEventList( sig, accepted, nEvents ); } else if ( genType == generatorType::TreePhaseSpace ) { - CoherentSum sig( eventType, MPS, "" ); + PolarisedSum sig( eventType, MPS, "" ); std::vector channels; for( auto& chain : sig.matrixElements() ) channels.push_back( chain.decayTree ); Generator signalGenerator(channels, eventType, &rand); diff --git a/doc/release.notes b/doc/release.notes index 3993a3d4296..c8b6404fe25 100644 --- a/doc/release.notes +++ b/doc/release.notes @@ -5,6 +5,8 @@ !----------------------------------------------------------------------------- !=================== AmpGen v1r2 2019-11-12 ================== - New phase space Generator TreePhaseSpace for producing narrow resonances. + - Improved handling of CP conjugated amplitudes. + - Add vertices f_fS_S{L,R} f_Vf_S{L,R} for couplings with well-defined chirality. !=================== AmpGen v1r2 2019-08-13 ================== - Tagged to match results in Gauss/LbAmpGen v49r14+ - Improved thread support for CoherentSum diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp index 5e6ec32f11b..51f0b3ff0a0 100644 --- a/examples/QcGenerator.cpp +++ b/examples/QcGenerator.cpp @@ -326,7 +326,7 @@ void add_CP_conjugate( MinuitParameterSet& mps ) std::string pname = tokens[0]; if ( reOrIm == "Re" || reOrIm == "Im" ){ auto p = Particle( pname ).conj(); - sgn = reOrIm == "Re" ? p.quasiCP() : 1; + sgn = reOrIm == "Re" ? p.CP() : 1; new_name = p.uniqueString() +"_"+reOrIm; } else if( tokens.size() == 2 ) { diff --git a/options/MintDalitzSpecialParticles.csv b/options/MintDalitzSpecialParticles.csv index 33ce6845fce..00c3a6774b6 100644 --- a/options/MintDalitzSpecialParticles.csv +++ b/options/MintDalitzSpecialParticles.csv @@ -14,35 +14,35 @@ 9.990E+03 ,1.0E+00,1.0E+00,9.9E+09 ,1.0E+00,1.0E+00,0 , ,1/2 ,+, ,F, 9988, 0,4,R,NonRes1p ,?? 9.990E+03 ,1.0E+00,1.0E+00,9.9E+09 ,1.0E+00,1.0E+00,0 , ,3/2 ,-, ,F, 9989, 0,4,R,NonRes3m ,?? 9.990E+03 ,1.0E+00,1.0E+00,9.9E+09 ,1.0E+00,1.0E+00,0 , ,3/2 ,+, ,F, 9910, 0,4,R,NonRes3p ,?? -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+, , 998100, 0, ,R,PiPi0 ,x(uU+dD)+y(sS) -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+, , 998101, 0, ,R,PiPi1 ,x(uU+dD)+y(sS) -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+, , 998102, 0, ,R,PiPi2 ,x(uU+dD)+y(sS) -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+, , 998103, 0, ,R,PiPi3 ,x(uU+dD)+y(sS) -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+, , 998104, 0, ,R,PiPi4 ,x(uU+dD)+y(sS) -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+, , 998105, 0, ,R,PiPi5 ,x(uU+dD)+y(sS) -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+, , 998106, 0, ,R,PiPi6 ,x(uU+dD)+y(sS) -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+,F, 998110, 0, ,R,KPi0 ,?? -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+,F, 998111, 0, ,R,KPi1 ,?? -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+,F, 998112, 0, ,R,KPi2 ,?? -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+,F, 998113, 0, ,R,KPi3 ,?? -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+,F, 998114, 0, ,R,KPi4 ,?? -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+,F, 998115, 0, ,R,KPi5 ,?? -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+,F, 998116, 0, ,R,KPi6 ,?? -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+,F, 998117, 0, ,R,KPi7 ,?? -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+, , 998120, 0, ,R,KK0 ,x(uU+dD)+y(sS) -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+, , 998121, 0, ,R,KK1 ,x(uU+dD)+y(sS) -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+, , 998122, 0, ,R,KK2 ,x(uU+dD)+y(sS) -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+, , 998123, 0, ,R,KK3 ,x(uU+dD)+y(sS) -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+, , 998124, 0, ,R,KK4 ,x(uU+dD)+y(sS) -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+, , 998125, 0, ,R,KK5 ,x(uU+dD)+y(sS) -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+, , 998126, 0, ,R,KK6 ,x(uU+dD)+y(sS) -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,1 ,-,-, , 998130, 0, ,R,rhoOmega0 ,?? -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,1 ,-,-, , 998131, 0, ,R,rhoOmega1 ,?? -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,1 ,-,-, , 998132, 0, ,R,rhoOmega2 ,?? -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,1 ,-,-, , 998133, 0, ,R,rhoOmega3 ,?? -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,1 ,-,-, , 998134, 0, ,R,rhoOmega4 ,?? -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,1 ,-,-, , 998135, 0, ,R,rhoOmega5 ,?? -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,1 ,-,-, , 998136, 0, ,R,rhoOmega6 ,?? +9.970E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+, , , 998100, 0, ,R,PiPi0 ,x(uU+dD)+y(sS) +9.970E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+, , , 998101, 0, ,R,PiPi1 ,x(uU+dD)+y(sS) +9.970E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+, , , 998102, 0, ,R,PiPi2 ,x(uU+dD)+y(sS) +9.970E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+, , , 998103, 0, ,R,PiPi3 ,x(uU+dD)+y(sS) +9.970E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+, , , 998104, 0, ,R,PiPi4 ,x(uU+dD)+y(sS) +9.970E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+, , , 998105, 0, ,R,PiPi5 ,x(uU+dD)+y(sS) +9.970E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+, , , 998106, 0, ,R,PiPi6 ,x(uU+dD)+y(sS) +9.980E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1/2,+,0 ,+,+,F, 998110, 0, ,R,KPi0 ,?? +9.980E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1/2,+,0 ,+,+,F, 998111, 0, ,R,KPi1 ,?? +9.980E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1/2,+,0 ,+,+,F, 998112, 0, ,R,KPi2 ,?? +9.980E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1/2,+,0 ,+,+,F, 998113, 0, ,R,KPi3 ,?? +9.980E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1/2,+,0 ,+,+,F, 998114, 0, ,R,KPi4 ,?? +9.980E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1/2,+,0 ,+,+,F, 998115, 0, ,R,KPi5 ,?? +9.980E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1/2,+,0 ,+,+,F, 998116, 0, ,R,KPi6 ,?? +9.980E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1/2,+,0 ,+,+,F, 998117, 0, ,R,KPi7 ,?? +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+, , , 998120, 0, ,R,KK0 ,x(uU+dD)+y(sS) +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+, , , 998121, 0, ,R,KK1 ,x(uU+dD)+y(sS) +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+, , , 998122, 0, ,R,KK2 ,x(uU+dD)+y(sS) +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+, , , 998123, 0, ,R,KK3 ,x(uU+dD)+y(sS) +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+, , , 998124, 0, ,R,KK4 ,x(uU+dD)+y(sS) +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+, , , 998125, 0, ,R,KK5 ,x(uU+dD)+y(sS) +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,0 ,+,0 ,+, , , 998126, 0, ,R,KK6 ,x(uU+dD)+y(sS) +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1 ,+,1 ,-,-, , 998130, 0, ,R,rhoOmega0 ,?? +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1 ,+,1 ,-,-, , 998131, 0, ,R,rhoOmega1 ,?? +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1 ,+,1 ,-,-, , 998132, 0, ,R,rhoOmega2 ,?? +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1 ,+,1 ,-,-, , 998133, 0, ,R,rhoOmega3 ,?? +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1 ,+,1 ,-,-, , 998134, 0, ,R,rhoOmega4 ,?? +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1 ,+,1 ,-,-, , 998135, 0, ,R,rhoOmega5 ,?? +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1 ,+,1 ,-,-, , 998136, 0, ,R,rhoOmega6 ,?? 1.272E+03 ,7.0E+00,7.0E+00,9.0E+01 ,2.0E+01,2.0E+01,1/2, ,1 ,+, ,F, 998200, +, ,R,Ka ,uS 1.272E+03 ,7.0E+00,7.0E+00,9.0E+01 ,2.0E+01,2.0E+01,1/2, ,1 ,+, ,F, 998201, +, ,R,Kb ,uS 1.86484E+03 ,1.7E-01,1.7E-01,1.605E-09 ,6.0E-12,6.0E-12,1/2, ,0 ,-, ,F, 998421, 0, ,R,D~ ,cU diff --git a/options/mass_width.csv b/options/mass_width.csv index 2895a7b12ac..50cacb48a00 100644 --- a/options/mass_width.csv +++ b/options/mass_width.csv @@ -104,9 +104,9 @@ 5.10998910E-01,1.3E-08,1.3E-08,0.0E+00 ,0.0E+00,0.0E+00, , ,1/2 ,+, ,B, 11, -, ,R,e , 1.05658367E+02,4.0E-06,4.0E-06,3.015937E-16,2.9E-21,2.9E-21, , ,1/2 ,+, ,B, 13, -, ,R,mu , 1.77684E+03 ,1.7E-01,1.7E-01,2.280E-09 ,8.0E-12,8.0E-12, , ,1/2 ,+, ,B, 15, -, ,R,tau , -0.0E+00 ,0.0E+00,0.0E+00,0.0E+00 ,0.0E+00,0.0E+00,<2 , ,1/2 ,+, ,F, 12, 0, ,R,nu_e , -0.0E+00 ,0.0E+00,0.0E+00,0.0E+00 ,0.0E+00,0.0E+00,<2 , ,1/2 ,+, ,F, 14, 0, ,R,nu_mu , -0.0E+00 ,0.0E+00,0.0E+00,0.0E+00 ,0.0E+00,0.0E+00,<2 , ,1/2 ,+, ,F, 16, 0, ,R,nu_tau , +0.0E+00 ,0.0E+00,0.0E+00,0.0E+00 ,0.0E+00,0.0E+00,<2 , ,1/2 ,+, ,F, 12, 0, ,R,nue , +0.0E+00 ,0.0E+00,0.0E+00,0.0E+00 ,0.0E+00,0.0E+00,<2 , ,1/2 ,+, ,F, 14, 0, ,R,numu , +0.0E+00 ,0.0E+00,0.0E+00,0.0E+00 ,0.0E+00,0.0E+00,<2 , ,1/2 ,+, ,F, 16, 0, ,R,nutau , 2.4E+00 ,9.0E-01,9.0E-01,-1 ,-1 ,-1 ,1/2, ,1/2 ,+, ,F, 2,+2/3, ,R,u ,u 4.8E+00 ,1.2E+00,1.2E+00,-1 ,-1 ,-1 ,1/2, ,1/2 ,+, ,F, 1,-1/3, ,R,d ,d 1.04E+02 ,2.6E+01,3.4E+01,-1 ,-1 ,-1 ,0 , ,1/2 ,+, ,F, 3,-1/3, ,R,s ,s @@ -118,12 +118,12 @@ 5.47853E+02 ,2.4E-02,2.4E-02,1.30E-03 ,7.0E-05,7.0E-05,0 ,+,0 ,-,+, , 221, 0, ,R,eta ,x(uU+dD)+y(sS) 8.0E+02 ,4.0E+02,4.0E+02,8.0E+02 ,2.0E+02,2.0E+02,0 ,+,0 ,+,+, ,9000221, 0, ,R,f(0)(600) ,Maybe non-qQ 7.7549E+02 ,3.4E-01,3.4E-01,1.4940E+02 ,1.0E+00,1.0E+00,1 ,+,1 ,-, ,B, 213, +, ,R,rho(770) ,uD -7.7549E+02 ,3.4E-01,3.4E-01,1.4940E+02 ,1.0E+00,1.0E+00,1 ,+,1 ,-,-,B, 113, 0, ,R,rho(770) ,(uU-dD)/sqrt(2) +7.7549E+02 ,3.4E-01,3.4E-01,1.4940E+02 ,1.0E+00,1.0E+00,1 ,+,1 ,-,-, , 113, 0, ,R,rho(770) ,(uU-dD)/sqrt(2) 7.8265E+02 ,1.2E-01,1.2E-01,8.49E+00 ,8.0E-02,8.0E-02,0 ,-,1 ,-,-, , 223, 0, ,R,omega(782) ,x(uU+dD)+y(sS) 9.5766E+02 ,2.4E-01,2.4E-01,2.05E-01 ,1.5E-02,1.5E-02,0 ,+,0 ,-,+, , 331, 0, ,R,eta'(958) ,x(uU+dD)+y(sS) 9.800E+02 ,1.0E+01,1.0E+01,7.0E+01 ,3.0E+01,3.0E+01,0 ,+,0 ,+,+, ,9010221, 0, ,R,f(0)(980) ,Maybe non-qQ 9.847E+02 ,1.2E+00,1.2E+00,7.5E+01 ,2.5E+01,2.5E+01,1 ,-,0 ,+, ,B,9000211, +, ,R,a(0)(980) ,Maybe non-qQ -9.847E+02 ,1.2E+00,1.2E+00,7.5E+01 ,2.5E+01,2.5E+01,1 ,-,0 ,+,+,B,9000111, 0, ,R,a(0)(980) ,Maybe non-qQ +9.847E+02 ,1.2E+00,1.2E+00,7.5E+01 ,2.5E+01,2.5E+01,1 ,-,0 ,+,+, ,9000111, 0, ,R,a(0)(980) ,Maybe non-qQ 1.019455E+03 ,2.0E-02,2.0E-02,4.26E+00 ,4.0E-02,4.0E-02,0 ,-,1 ,-,-, , 333, 0, ,R,phi(1020) ,x(uU+dD)+y(sS) 1.170E+03 ,2.0E+01,2.0E+01,3.6E+02 ,4.0E+01,4.0E+01,0 ,-,1 ,+,-, , 10223, 0, ,R,h(1)(1170) ,x(uU+dD)+y(sS) 1.2295E+03 ,3.2E+00,3.2E+00,1.42E+02 ,9.0E+00,9.0E+00,1 ,+,1 ,+, ,B, 10213, +, ,R,b(1)(1235) ,uD @@ -134,9 +134,9 @@ 1.2818E+03 ,6.0E-01,6.0E-01,2.43E+01 ,1.1E+00,1.1E+00,0 ,+,1 ,+,+, , 20223, 0, ,R,f(1)(1285) ,x(uU+dD)+y(sS) 1.294E+03 ,4.0E+00,4.0E+00,5.5E+01 ,5.0E+00,5.0E+00,0 ,+,0 ,-,+, , 100221, 0, ,R,eta(1295) ,x(uU+dD)+y(sS) 1.300E+03 ,1.0E+02,1.0E+02,4.0E+02 ,2.0E+02,2.0E+02,1 ,-,0 ,-, ,B, 100211, +, ,R,pi(1300) ,uD -1.300E+03 ,1.0E+02,1.0E+02,4.0E+02 ,2.0E+02,2.0E+02,1 ,-,0 ,-,+,B, 100111, 0, ,R,pi(1300) ,(uU-dD)/sqrt(2) +1.300E+03 ,1.0E+02,1.0E+02,4.0E+02 ,2.0E+02,2.0E+02,1 ,-,0 ,-,+, , 100111, 0, ,R,pi(1300) ,(uU-dD)/sqrt(2) 1.3183E+03 ,6.0E-01,6.0E-01,1.07E+02 ,5.0E+00,5.0E+00,1 ,-,2 ,+, ,B, 215, +, ,R,a(2)(1320) ,uD -1.3183E+03 ,6.0E-01,6.0E-01,1.07E+02 ,5.0E+00,5.0E+00,1 ,-,2 ,+,+,B, 115, 0, ,R,a(2)(1320) ,(uU-dD)/sqrt(2) +1.3183E+03 ,6.0E-01,6.0E-01,1.07E+02 ,5.0E+00,5.0E+00,1 ,-,2 ,+,+, , 115, 0, ,R,a(2)(1320) ,(uU-dD)/sqrt(2) 1.35E+03 ,1.5E+02,1.5E+02,3.5E+02 ,1.5E+02,1.5E+02,0 ,+,0 ,+,+, , 30221, 0, ,R,f(0)(1370) ,x(uU+dD)+y(sS) 1.386E+03 ,1.9E+01,1.9E+01,9.1E+01 ,3.0E+01,3.0E+01,? ,-,1 ,+,-, , 10333, 0, ,S,h(1)(1380) ,x(uU+dD)+y(sS) 1.351E+03 ,3.0E+01,3.0E+01,3.1E+02 ,4.0E+01,4.0E+01,1 ,-,1 ,-, , ,9000213, +, ,R,pi(1)(1400) ,Maybe non-qQ @@ -146,9 +146,9 @@ 1.425E+03 ,2.5E+01,2.5E+01,2.15E+02 ,3.5E+01,3.5E+01,0 ,-,1 ,-,-, , 100223, 0, ,R,omega(1420) ,x(uU+dD)+y(sS) 1.453E+03 ,4.0E+00,4.0E+00,1.3E+01 ,5.0E+00,5.0E+00,0 ,+,2 ,+,+, ,9000225, 0, ,S,f(2)(1430) ,x(uU+dD)+y(sS) 1.474E+03 ,1.9E+01,1.9E+01,2.65E+02 ,1.3E+01,1.3E+01,1 ,-,0 ,+, ,B, 10211, +, ,R,a(0)(1450) ,uD -1.474E+03 ,1.9E+01,1.9E+01,2.65E+02 ,1.3E+01,1.3E+01,1 ,-,0 ,+,+,B, 10111, 0, ,R,a(0)(1450) ,(uU-dD)/sqrt(2) +1.474E+03 ,1.9E+01,1.9E+01,2.65E+02 ,1.3E+01,1.3E+01,1 ,-,0 ,+,+, , 10111, 0, ,R,a(0)(1450) ,(uU-dD)/sqrt(2) 1.465E+03 ,2.5E+01,2.5E+01,4.0E+02 ,6.0E+01,6.0E+01,1 ,+,1 ,-, ,B, 100213, +, ,R,rho(1450) ,uD -1.465E+03 ,2.5E+01,2.5E+01,4.0E+02 ,6.0E+01,6.0E+01,1 ,+,1 ,-,-,B, 100113, 0, ,R,rho(1450) ,(uU-dD)/sqrt(2) +1.465E+03 ,2.5E+01,2.5E+01,4.0E+02 ,6.0E+01,6.0E+01,1 ,+,1 ,-,-, , 100113, 0, ,R,rho(1450) ,(uU-dD)/sqrt(2) 1.476E+03 ,4.0E+00,4.0E+00,8.5E+01 ,9.0E+00,9.0E+00,0 ,+,0 ,-,+, , 100331, 0, ,R,eta(1475) ,x(uU+dD)+y(sS) 1.505E+03 ,6.0E+00,6.0E+00,1.09E+02 ,7.0E+00,7.0E+00,0 ,+,0 ,+,+, ,9030221, 0, ,R,f(0)(1500) ,Maybe non-qQ 1.518E+03 ,5.0E+00,5.0E+00,7.3E+01 ,2.5E+01,2.5E+01,0 ,+,1 ,+,+, ,9000223, 0, ,S,f(1)(1510) ,x(uU+dD)+y(sS) @@ -159,61 +159,61 @@ 1.662E+03 ,1.5E+01,1.1E+01,2.3E+02 ,5.0E+01,5.0E+01,1 ,-,1 ,-, , ,9010213, +, ,R,pi(1)(1600) ,Maybe non-qQ 1.662E+03 ,1.5E+01,1.1E+01,2.3E+02 ,5.0E+01,5.0E+01,1 ,-,1 ,-,+, ,9010113, 0, ,R,pi(1)(1600) ,Maybe non-qQ 1.647E+03 ,2.2E+01,2.2E+01,2.54E+02 ,2.7E+01,2.7E+01,1 ,-,1 ,+, ,B,9020213, +, ,S,a(1)(1640) ,uD -1.647E+03 ,2.2E+01,2.2E+01,2.54E+02 ,2.7E+01,2.7E+01,1 ,-,1 ,+,+,B,9020113, 0, ,S,a(1)(1640) ,(uU-dD)/sqrt(2) +1.647E+03 ,2.2E+01,2.2E+01,2.54E+02 ,2.7E+01,2.7E+01,1 ,-,1 ,+,+, ,9020113, 0, ,S,a(1)(1640) ,(uU-dD)/sqrt(2) 1.639E+03 ,6.0E+00,6.0E+00,9.9E+01 ,6.0E+01,4.0E+01,0 ,+,2 ,+,+, ,9020225, 0, ,S,f(2)(1640) ,x(uU+dD)+y(sS) 1.617E+03 ,5.0E+00,5.0E+00,1.81E+02 ,1.1E+01,1.1E+01,0 ,+,2 ,-,+, , 10225, 0, ,R,eta(2)(1645) ,x(uU+dD)+y(sS) 1.670E+03 ,3.0E+01,3.0E+01,3.15E+02 ,3.5E+01,3.5E+01,0 ,-,1 ,-,-, , 30223, 0, ,R,omega(1650) ,x(uU+dD)+y(sS) 1.667E+03 ,4.0E+00,4.0E+00,1.680E+02 ,1.0E+01,1.0E+01,0 ,-,3 ,-,-, , 227, 0, ,R,omega(3)(1670) ,x(uU+dD)+y(sS) 1.6724E+03 ,3.2E+00,3.2E+00,2.59E+02 ,9.0E+00,9.0E+00,1 ,-,2 ,-, ,B, 10215, +, ,R,pi(2)(1670) ,uD -1.6724E+03 ,3.2E+00,3.2E+00,2.59E+02 ,9.0E+00,9.0E+00,1 ,-,2 ,-,+,B, 10115, 0, ,R,pi(2)(1670) ,(uU-dD)/sqrt(2) +1.6724E+03 ,3.2E+00,3.2E+00,2.59E+02 ,9.0E+00,9.0E+00,1 ,-,2 ,-,+, , 10115, 0, ,R,pi(2)(1670) ,(uU-dD)/sqrt(2) 1.680E+03 ,2.0E+01,2.0E+01,1.5E+02 ,5.0E+01,5.0E+01,0 ,-,1 ,-,-, , 100333, 0, ,R,phi(1680) ,x(uU+dD)+y(sS) 1.6888E+03 ,2.1E+00,2.1E+00,1.610E+02 ,1.0E+01,1.0E+01,1 ,+,3 ,-, ,B, 217, +, ,R,rho(3)(1690) ,uD -1.6888E+03 ,2.1E+00,2.1E+00,1.610E+02 ,1.0E+01,1.0E+01,1 ,+,3 ,-,-,B, 117, 0, ,R,rho(3)(1690) ,(uU-dD)/sqrt(2) +1.6888E+03 ,2.1E+00,2.1E+00,1.610E+02 ,1.0E+01,1.0E+01,1 ,+,3 ,-,-, , 117, 0, ,R,rho(3)(1690) ,(uU-dD)/sqrt(2) 1.720E+03 ,2.0E+01,2.0E+01,2.50E+02 ,1.0E+02,1.0E+02,1 ,+,1 ,-, ,B, 30213, +, ,R,rho(1700) ,uD -1.720E+03 ,2.0E+01,2.0E+01,2.50E+02 ,1.0E+02,1.0E+02,1 ,+,1 ,-,-,B, 30113, 0, ,R,rho(1700) ,(uU-dD)/sqrt(2) +1.720E+03 ,2.0E+01,2.0E+01,2.50E+02 ,1.0E+02,1.0E+02,1 ,+,1 ,-,-, , 30113, 0, ,R,rho(1700) ,(uU-dD)/sqrt(2) 1.732E+03 ,1.6E+01,1.6E+01,1.9E+02 ,4.0E+01,4.0E+01,1 ,-,2 ,+, ,B, 100215, +, ,S,a(2)(1700) ,uD -1.732E+03 ,1.6E+01,1.6E+01,1.9E+02 ,4.0E+01,4.0E+01,1 ,-,2 ,+,+,B, 100115, 0, ,S,a(2)(1700) ,(uU-dD)/sqrt(2) +1.732E+03 ,1.6E+01,1.6E+01,1.9E+02 ,4.0E+01,4.0E+01,1 ,-,2 ,+,+, , 100115, 0, ,S,a(2)(1700) ,(uU-dD)/sqrt(2) 1.724E+03 ,7.0E+00,7.0E+00,1.37E+02 ,8.0E+00,8.0E+00,0 ,+,0 ,+,+, , 10331, 0, ,R,f(0)(1710) ,x(uU+dD)+y(sS) 1.756E+03 ,9.0E+00,9.0E+00,9.6E+01 ,7.0E+01,7.0E+01,0 ,+,0 ,-,+, ,9040221, 0, ,S,eta(1760) ,x(uU+dD)+y(sS) 1.816E+03 ,1.4E+01,1.4E+01,2.08E+02 ,1.2E+01,1.2E+01,1 ,-,0 ,-, ,B,9010211, +, ,R,pi(1800) ,uD -1.816E+03 ,1.4E+01,1.4E+01,2.08E+02 ,1.2E+01,1.2E+01,1 ,-,0 ,-,+,B,9010111, 0, ,R,pi(1800) ,(uU-dD)/sqrt(2) +1.816E+03 ,1.4E+01,1.4E+01,2.08E+02 ,1.2E+01,1.2E+01,1 ,-,0 ,-,+, ,9010111, 0, ,R,pi(1800) ,(uU-dD)/sqrt(2) 1.815E+03 ,1.2E+01,1.2E+01,1.97E+02 ,2.2E+01,2.2E+01,0 ,+,2 ,+,+, ,9030225, 0, ,S,f(2)(1810) ,x(uU+dD)+y(sS) 1.834E+03 ,7.0E+00,7.0E+00,6.8E+01 ,2.2E+01,2.2E+01,? ,?,? ,-,+, , , 0, ,S,X(1835) ,x(uU+dD)+y(sS) 1.854E+03 ,7.0E+00,7.0E+00,8.7E+01 ,2.8E+01,2.3E+01,0 ,-,3 ,-,-, , 337, 0, ,R,phi(3)(1850) ,x(uU+dD)+y(sS) 1.842E+03 ,8.0E+00,8.0E+00,2.25E+02 ,1.4E+01,1.4E+01,0 ,+,2 ,-,+, , 10335, 0, ,S,eta(2)(1870) ,x(uU+dD)+y(sS) 1.895E+03 ,1.6E+01,1.6E+01,2.35E+02 ,3.4E+01,3.4E+01,1 ,-,2 ,-,+, , , 0, ,R,pi(2)(1880) ,x(uU+dD)+y(sS) 1.909E+03 ,3.0E+01,3.0E+01,4.8E+01 ,1.7E+01,1.7E+01,1 ,+,1 ,-, ,B,9030213, +, ,S,rho(1900) ,uD -1.909E+03 ,3.0E+01,3.0E+01,4.8E+01 ,1.7E+01,1.7E+01,1 ,+,1 ,-,-,B,9030113, 0, ,S,rho(1900) ,(uU-dD)/sqrt(2) +1.909E+03 ,3.0E+01,3.0E+01,4.8E+01 ,1.7E+01,1.7E+01,1 ,+,1 ,-,-, ,9030113, 0, ,S,rho(1900) ,(uU-dD)/sqrt(2) 1.903E+03 ,9.0E+00,9.0E+00,1.96E+02 ,3.1E+01,3.1E+01,0 ,+,2 ,+,+, ,9040225, 0, ,S,f(2)(1910) ,x(uU+dD)+y(sS) 1.944E+03 ,1.2E+01,1.2E+01,4.72E+02 ,1.8E+01,1.8E+01,0 ,+,2 ,+,+, ,9050225, 0, ,R,f(2)(1950) ,x(uU+dD)+y(sS) 1.982E+03 ,1.4E+01,1.4E+01,1.88E+02 ,2.4E+01,2.4E+01,1 ,+,3 ,-, ,B,9000217, +, ,S,rho(3)(1990) ,uD -1.982E+03 ,1.4E+01,1.4E+01,1.88E+02 ,2.4E+01,2.4E+01,1 ,+,3 ,-,-,B,9000117, 0, ,S,rho(3)(1990) ,(uU-dD)/sqrt(2) +1.982E+03 ,1.4E+01,1.4E+01,1.88E+02 ,2.4E+01,2.4E+01,1 ,+,3 ,-,-, ,9000117, 0, ,S,rho(3)(1990) ,(uU-dD)/sqrt(2) 2.01E+03 ,6.0E+01,8.0E+01,2.0E+02 ,6.0E+01,6.0E+01,0 ,+,2 ,+,+, ,9060225, 0, ,R,f(2)(2010) ,x(uU+dD)+y(sS) 1.992E+03 ,1.6E+01,1.6E+01,4.4E+02 ,6.0E+01,6.0E+01,0 ,+,0 ,+,+, ,9050221, 0, ,S,f(0)(2020) ,x(uU+dD)+y(sS) 2.0010E+03 ,1.0E+01,1.0E+01,3.13E+02 ,3.1E+01,3.1E+01,1 ,-,4 ,+, ,B, 219, +, ,R,a(4)(2040) ,uD -2.0010E+03 ,1.0E+01,1.0E+01,3.13E+02 ,3.1E+01,3.1E+01,1 ,-,4 ,+,+,B, 119, 0, ,R,a(4)(2040) ,(uU-dD)/sqrt(2) +2.0010E+03 ,1.0E+01,1.0E+01,3.13E+02 ,3.1E+01,3.1E+01,1 ,-,4 ,+,+, , 119, 0, ,R,a(4)(2040) ,(uU-dD)/sqrt(2) 2.018E+03 ,1.1E+01,1.1E+01,2.37E+02 ,1.8E+01,1.8E+01,0 ,+,4 ,+,+, , 229, 0, ,R,f(4)(2050) ,x(uU+dD)+y(sS) 2.090E+03 ,2.9E+01,2.9E+01,6.2E+02 ,5.0E+01,5.0E+01,1 ,-,2 ,-, ,B,9000215, +, ,S,pi(2)(2100) ,uD -2.090E+03 ,2.9E+01,2.9E+01,6.2E+02 ,5.0E+01,5.0E+01,1 ,-,2 ,-,+,B,9000115, 0, ,S,pi(2)(2100) ,(uU-dD)/sqrt(2) +2.090E+03 ,2.9E+01,2.9E+01,6.2E+02 ,5.0E+01,5.0E+01,1 ,-,2 ,-,+, ,9000115, 0, ,S,pi(2)(2100) ,(uU-dD)/sqrt(2) 2.103E+03 ,8.0E+00,8.0E+00,2.09E+02 ,1.9E+01,1.9E+01,0 ,+,0 ,+,+, ,9060221, 0, ,S,f(0)(2100) ,x(uU+dD)+y(sS) 2.156E+03 ,1.1E+01,1.1E+01,1.67E+02 ,3.0E+01,3.0E+01,0 ,+,2 ,+,+, ,9070225, 0, ,S,f(2)(2150) ,x(uU+dD)+y(sS) 2.149E+03 ,1.7E+01,1.7E+01,3.6E+02 ,4.0E+01,4.0E+01,1 ,+,1 ,-, ,B,9040213, +, ,S,rho(2150) ,uD -2.149E+03 ,1.7E+01,1.7E+01,3.6E+02 ,4.0E+01,4.0E+01,1 ,+,1 ,-,-,B,9040113, 0, ,S,rho(2150) ,(uU-dD)/sqrt(2) +2.149E+03 ,1.7E+01,1.7E+01,3.6E+02 ,4.0E+01,4.0E+01,1 ,+,1 ,-,-, ,9040113, 0, ,S,rho(2150) ,(uU-dD)/sqrt(2) 2.175E+03 ,1.5E+01,1.5E+01,6.1E+01 ,1.8E+01,1.8E+01,0 ,-,1 ,-, ,B, , +, ,S,phi(2170) ,uD -2.175E+03 ,1.5E+01,1.5E+01,6.1E+01 ,1.8E+01,1.8E+01,0 ,-,1 ,-,-,B, , 0, ,S,phi(2170) ,(uU-dD)/sqrt(2) +2.175E+03 ,1.5E+01,1.5E+01,6.1E+01 ,1.8E+01,1.8E+01,0 ,-,1 ,-,-, , , 0, ,S,phi(2170) ,(uU-dD)/sqrt(2) 2.189E+03 ,1.3E+01,1.3E+01,2.4E+02 ,5.0E+01,5.0E+01,0 ,+,0 ,+,+, ,9070221, 0, ,S,f(0)(2200) ,x(uU+dD)+y(sS) 2.2311E+03 ,3.5E+00,3.5E+00,2.3E+01 ,8.0E+00,7.0E+00,0 ,+,2 ,+,+, ,9000229, 0, ,S,f(J)(2220) ,x(uU+dD)+y(sS) 2.220E+03 ,1.8E+01,1.8E+01,1.5E+02 ,3.1E+02,8.0E+01,0 ,+,0 ,-,+, ,9080221, 0, ,S,eta(2225) ,x(uU+dD)+y(sS) 2.260E+03 ,2.0E+01,2.0E+01,1.60E+02 ,2.5E+01,2.5E+01,1 ,+,3 ,-, ,B,9010217, +, ,S,rho(3)(2250) ,uD -2.260E+03 ,2.0E+01,2.0E+01,1.60E+02 ,2.5E+01,2.5E+01,1 ,+,3 ,-,-,B,9010117, 0, ,S,rho(3)(2250) ,(uU-dD)/sqrt(2) +2.260E+03 ,2.0E+01,2.0E+01,1.60E+02 ,2.5E+01,2.5E+01,1 ,+,3 ,-,-, ,9010117, 0, ,S,rho(3)(2250) ,(uU-dD)/sqrt(2) 2.297E+03 ,2.8E+01,2.8E+01,1.5E+02 ,4.0E+01,4.0E+01,0 ,+,2 ,+,+, ,9080225, 0, ,R,f(2)(2300) ,x(uU+dD)+y(sS) 2.32E+03 ,6.0E+01,6.0E+01,2.5E+02 ,8.0E+01,8.0E+01,0 ,+,4 ,+,+, ,9010229, 0, ,S,f(4)(2300) ,x(uU+dD)+y(sS) 2.314E+03 ,2.5E+01,2.5E+01,1.44E+02 ,2.0E+01,2.0E+01,0 ,+,0 ,+,+, ,9090221, 0, ,S,f(0)(2330) ,x(uU+dD)+y(sS) 2.34E+03 ,6.0E+01,6.0E+01,3.2E+02 ,8.0E+01,7.0E+01,0 ,+,2 ,+,+, ,9090225, 0, ,R,f(2)(2340) ,x(uU+dD)+y(sS) 2.330E+03 ,3.5E+01,3.5E+01,4.00E+02 ,1.0E+02,1.0E+02,1 ,+,5 ,-, ,B, , +, ,S,rho(5)(2350) ,uD -2.330E+03 ,3.5E+01,3.5E+01,4.00E+02 ,1.0E+02,1.0E+02,1 ,+,5 ,-,-,B, , 0, ,S,rho(5)(2350) ,(uU+dD)/sqrt(2) +2.330E+03 ,3.5E+01,3.5E+01,4.00E+02 ,1.0E+02,1.0E+02,1 ,+,5 ,-,-, , , 0, ,S,rho(5)(2350) ,(uU+dD)/sqrt(2) 2.45E+03 ,1.3E+02,1.3E+02,4.0E+02 ,2.5E+02,2.5E+02,1 ,-,6 ,+, ,B, , +, ,S,a(6)(2450) ,uD -2.45E+03 ,1.3E+02,1.3E+02,4.0E+02 ,2.5E+02,2.5E+02,1 ,-,6 ,+,+,B, , 0, ,S,a(6)(2450) ,(uU+dD)/sqrt(2) +2.45E+03 ,1.3E+02,1.3E+02,4.0E+02 ,2.5E+02,2.5E+02,1 ,-,6 ,+,+, , , 0, ,S,a(6)(2450) ,(uU+dD)/sqrt(2) 2.46E+03 ,5.0E+01,5.0E+01,2.6E+02 ,4.0E+01,4.0E+01,0 ,+,6 ,+,+, , , 0, ,S,f(6)(2510) ,x(uU+dD)+y(sS) 1.0724E+03 ,8.0E-01,8.0E-01,3.50E+00 ,1.5E+00,1.0E+00,? ,?,0 ,+,+, , , 0, ,F,X(1070) ,?? 1.107E+03 ,4.0E+00,4.0E+00,1.11E+02 ,1.7E+01,1.7E+01,0 ,+,? ,+,+, , , 0, ,F,X(1110) ,?? @@ -367,7 +367,7 @@ 3.054E+03 ,1.1E+01,1.1E+01,4.2E+01 ,1.6E+01,1.6E+01,? ,?,? ,?,?, , , 0, ,S,K(3100) ,Maybe non-qQ 1.86962E+03 ,2.0E-01,2.0E-01,6.329E-10 ,4.0E-12,4.0E-12,1/2, ,0 ,-, ,B, 411, +, ,R,D ,cD 1.86484E+03 ,1.7E-01,1.7E-01,1.605E-09 ,6.0E-12,6.0E-12,1/2, ,0 ,-, ,F, 421, 0, ,R,D ,cU -2.00697E+03 ,1.9E-01,1.9E-01,2.1 ,-1 ,-1 ,1/2, ,1 ,-, ,F, 423, 0, ,R,D*(2007) ,cU +2.00697E+03 ,1.9E-01,1.9E-01,9.6E-02 ,-1 ,-1 ,1/2, ,1 ,-, ,F, 423, 0, ,R,D*(2007) ,cU 2.01027E+03 ,1.7E-01,1.7E-01,9.6E-02 ,2.2E-02,2.2E-02,1/2, ,1 ,-, ,B, 413, +, ,R,D*(2010) ,cD 2.35E+03 ,5.0E+01,5.0E+01,2.6E+02 ,5.0E+01,5.0E+01,1/2, ,0 ,+, ,F, 10421, 0, ,S,D(0)*(2400) ,cU 2.40E+03 ,4.0E+01,4.0E+01,2.8E+02 ,4.0E+01,4.0E+01,1/2, ,0 ,+, ,F, 10411, +, ,S,D(0)*(2400) ,cD @@ -378,7 +378,7 @@ 2.4601E+03 ,2.6E+00,3.5E+00,3.7E+01 ,6.0E+00,6.0E+00,1/2, ,2 ,+, ,B, 415, +, ,R,D(2)*(2460) ,cD 2.637E+03 ,6.0E+00,6.0E+00,15 ,-1 ,-1 ,1/2, ,? ,?, ,F, , +, ,S,D*(2640) ,cD 1.96849E+03 ,3.4E-01,3.4E-01,1.325E-09 ,1.9E-11,1.9E-11,0 , ,0 ,-, ,B, 431, +, ,R,D(s) ,cS -2.1123E+03 ,5.0E-01,5.0E-01,-1 ,-1 ,-1 ,0 , ,1 ,-, ,B, 433, +, ,R,D(s)* ,cS +2.1123E+03 ,5.0E-01,5.0E-01,1.0E-01 ,-1 ,-1 ,0 , ,1 ,-, ,B, 433, +, ,R,D(s)* ,cS 2.3178E+03 ,6.0E-01,6.0E-01,10 ,-1 ,-1 ,0 , ,0 ,+, ,B, 10431, +, ,R,D(s0)*(2317) ,cS 2.4596E+03 ,6.0E-01,6.0E-01,6.3 ,-1 ,-1 ,0 , ,1 ,+, ,B, 20433, +, ,R,D(s1)(2460) ,cS 2.5354E+03 ,6.0E-01,6.0E-01,2.5 ,-1 ,-1 ,0 , ,1 ,+, ,B, 10433, +, ,R,D(s1)(2536) ,cS diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 0db0cb76e90..f40b97ef6b0 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -125,9 +125,9 @@ void CoherentSum::debug( const Event& evt, const std::string& nameMustContain ) INFO( std::setw(70) << me.decayTree.uniqueString() << " A = [ " << std::real(A) << " " << std::imag(A) << " ] g = [ "<< std::real(me.coupling()) << " " << std::imag(me.coupling()) << " ] " - << me.decayTree.quasiCP() ); + << me.decayTree.CP() ); + if( m_dbThis ) me.amp.debug( evt.address() ); - //me.coupling.print(); } else for ( auto& me : m_matrixElements ) diff --git a/src/EventType.cpp b/src/EventType.cpp index d679dfa51dd..ffbabe1b3bd 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -39,7 +39,7 @@ EventType::EventType( const std::vector& particleNames, const bool& ERROR( "Particle not found: " << m_mother ); return; } - m_alt_part_names = NamedParameter("EventType::AlternativeParicleNames", false ); + m_alt_part_names = NamedParameter("EventType::AlternativeParticleNames", false ); for ( auto& particle : m_particleNames ) { auto prop = ParticlePropertiesList::get( particle ); if ( prop != nullptr ) @@ -49,9 +49,9 @@ EventType::EventType( const std::vector& particleNames, const bool& return; } if(m_alt_part_names) - m_particleNamesPickled.push_back( replaceAll( replaceAll( particle, "+", "p" ), "-", "m" ) ); + m_particleNamesPickled.push_back( replaceAll( particle, {{"+","p"},{"-","m"},{"(",""},{")",""}})); else - m_particleNamesPickled.push_back( replaceAll( replaceAll( particle, "+", "~" ), "-", "#" ) ); + m_particleNamesPickled.push_back( replaceAll( particle, {{"+","~"},{"-","#"},{"(",""},{")",""}})); } DEBUG( m_mother << " = " << m_motherMass << " -> " ); for ( unsigned int i = 0; i < m_particleNames.size(); ++i ) { diff --git a/src/Minimiser.cpp b/src/Minimiser.cpp index c64b0ec25c5..b5b3cefd3d2 100644 --- a/src/Minimiser.cpp +++ b/src/Minimiser.cpp @@ -106,6 +106,19 @@ bool Minimiser::doFit() } } m_status = m_minimiser->Status(); + for( unsigned i = 0 ; i != m_nParams; ++i ){ + double low = 0; + double high = 0; + int status = 0; + m_minimiser->GetMinosError(i, low, high, status); + auto param = m_parSet->at( m_mapping[i] ); + param->setResult( *param, param->err(), low, high ); + } + for( unsigned i = 0 ; i != m_nParams; ++i ) + { + auto param = m_parSet->at( m_mapping[i] ); + INFO( param->name() << " " << param->mean() << " " << param->errPos() << " " << param->errNeg() ); + } return 1; } @@ -155,3 +168,4 @@ void Minimiser::addExtendedTerm( IExtendLikelihood* m_term ) } ROOT::Minuit2::Minuit2Minimizer* Minimiser::minimiserInternal() { return m_minimiser; } + diff --git a/src/MinuitParameterSet.cpp b/src/MinuitParameterSet.cpp index 2b519c01eb3..f792a31d672 100644 --- a/src/MinuitParameterSet.cpp +++ b/src/MinuitParameterSet.cpp @@ -202,21 +202,23 @@ void MinuitParameterSet::resetToInit() for ( auto& param : *this ) param->resetToInit(); } -void MinuitParameterSet::rename(const std::string& name, const std::string& new_name) + +bool MinuitParameterSet::rename(const std::string& name, const std::string& new_name) { auto it = find(name); if( it == nullptr ){ - ERROR("Parameter: " << name << " not found"); - return; + DEBUG("Parameter: " << name << " not found"); + return false; } - if( name == new_name ) return; + if( name == new_name ) return false; if( find(new_name) != nullptr ){ - // ERROR("New key for " << name << " = " << new_name << " already exists"); - return; + DEBUG("New key for " << name << " = " << new_name << " already exists"); + return false; } it->setName(new_name); m_keyAccess.erase(name); m_keyAccess.emplace(new_name, it); + return true; } MinuitParameter* MinuitParameterSet::addOrGet( const std::string& name, const Flag& flag, const double& mean, diff --git a/src/Particle.cpp b/src/Particle.cpp index 2f2598762ca..0ce27e91570 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -37,7 +37,8 @@ Particle::Particle() {"Dirac", "Quantises along the z-axis"} , {"Weyl" , "Quantises along the direction of motion"}} ) )} , m_defaultModifier { NamedParameter("Particle::DefaultModifier","", "Default modifier to use for lineshapes, for example to use normalised vs unnormalised Blatt-Weisskopf factors.") } - {} + , m_cpOrderConvention {NamedParameter("Particle::CPOrderingConvention",true, "Making ordering of particles robust to CP conjugation")} +{} Particle::Particle( const std::string& name, const Particle& p1, const Particle& p2 ) : Particle() @@ -126,8 +127,7 @@ bool Particle::isValidDecayDescriptor( const std::string& decayDescriptor ) void Particle::parseModifier( const std::string& mod ) { - if ( Lineshape::Factory::isLineshape( mod ) ) - m_lineshape = mod; + if ( Lineshape::Factory::isLineshape(mod) ) m_lineshape = mod; else if( mod.size() == 1 ) { DEBUG( "Modifier = " << mod ); @@ -138,9 +138,14 @@ void Particle::parseModifier( const std::string& mod ) else if ( mod == "G" ) m_orbital = 4; else if ( mod == "H" ) m_orbital = 5; else if ( mod == "I" ) m_orbital = 6; - bool status=true; - auto tmp = lexical_cast(mod,status); - if( status ) m_spinConfigurationNumber = tmp; + else { + bool status=true; + auto tmp = lexical_cast(mod,status); // this is if it is a number /// + if( status ) m_spinConfigurationNumber = tmp; + else { + m_spinConfigurationNumber = 10 + int(mod[0]); + } + } } else if ( mod.size() == 2 ) { @@ -152,24 +157,6 @@ void Particle::parseModifier( const std::string& mod ) double Particle::spin() const { return double( m_props->twoSpin() / 2. ) ; } double Particle::S() const { return m_spinConfigurationNumber ; } -std::string Particle::vertexName() const -{ - if ( m_daughters.size() != 2 ){ - WARNING("Vertices only well-defined for quasi two-body processes, check logic"); - return "ERROR"; - } - std::string orbitalString; - if( m_orbital == 0 ) orbitalString = "S"; - if( m_orbital == 1 ) orbitalString = "P"; - if( m_orbital == 2 ) orbitalString = "D"; - if( m_orbital == 3 ) orbitalString = "F"; - if( m_spinConfigurationNumber != 0 ) orbitalString += std::to_string( m_spinConfigurationNumber ); - auto vx= m_props->spinName() + "_" + - m_daughters[0]->m_props->spinName() + - m_daughters[1]->m_props->spinName() + "_" + orbitalString; - return vx; -} - void Particle::pdgLookup() { if ( m_props == nullptr ) { @@ -177,7 +164,7 @@ void Particle::pdgLookup() return; } if ( m_lineshape == "BW" || m_usesDefaultLineshape ) { - if ( m_name.find("NonRes") != std::string::npos || m_props->width() < 1e-3 ) m_lineshape = "FormFactor"; + if ( m_name.find("NonRes") != std::string::npos || m_props->width() < ParticlePropertiesList::getMe()->quasiStableThreshold() ) m_lineshape = "FormFactor"; if ( m_name == "gamma0" ) m_lineshape = "Photon"; m_usesDefaultLineshape = true; } @@ -257,14 +244,13 @@ std::shared_ptr Particle::daughter( const std::string& name, const int std::string Particle::orbitalString() const { - std::string orbital_part; - if ( m_orbital == 0 ) orbital_part = "S"; - else if ( m_orbital == 1 ) orbital_part = "P"; - else if ( m_orbital == 2 ) orbital_part = "D"; - else if ( m_orbital == 3 ) orbital_part = "F"; - else orbital_part = "X"; - if( m_spinConfigurationNumber == 0 ) return orbital_part; - else return orbital_part + std::to_string( m_spinConfigurationNumber ); + constexpr std::array orbitals = {'S','P','D','F','G','H','I'}; + std::string rt = std::string(1, orbitals[m_orbital] ); + if( m_spinConfigurationNumber != 0 ){ + if( m_spinConfigurationNumber < 10 ) rt += std::to_string( m_spinConfigurationNumber ); + else rt += char(m_spinConfigurationNumber-10); + } + return rt; } bool Particle::hasModifier( const std::string& modifier ) const @@ -291,9 +277,9 @@ std::string Particle::makeUniqueString() { std::string modifier = modifierString(); if ( m_daughters.size() != 0 ) { - m_uniqueString = m_name + modifier + "{" + vectorToString( m_daughters, ",", [](auto& d){ return d->makeUniqueString() ;} ) +"}"; + m_uniqueString = m_props->name() + modifier + "{" + vectorToString( m_daughters, ",", [](auto& d){ return d->makeUniqueString() ;} ) +"}"; } else { - m_uniqueString = m_name + modifier ; + m_uniqueString = m_props->name() + modifier ; } return m_uniqueString; } @@ -477,9 +463,10 @@ Tensor Particle::spinTensor( DebugSymbols* db ) const return S; } else if ( m_daughters.size() == 2 ) { + auto vname = m_props->spinName() + "_" + m_daughters[0]->m_props->spinName() + m_daughters[1]->m_props->spinName() + "_" + orbitalString(); Tensor value = Vertex::Factory::getSpinFactor( P(), Q(), - daughter(0)->spinTensor( db ), - daughter(1)->spinTensor( db ), vertexName() , db ); + daughter(0)->spinTensor(db), + daughter(1)->spinTensor(db), vname, db ); DEBUG( "Returning spin tensor" ); return value; } else if ( m_daughters.size() == 3 ) { @@ -625,10 +612,20 @@ std::string Particle::texLabel( const bool& printHead, const bool& recurse ) con void Particle::sortDaughters() { - std::stable_sort( m_daughters.begin(), m_daughters.end(), - []( auto& A, auto& B ) { return *A < *B; } ); + bool isAntiParticle = m_props->pdgID() < 0; + if( m_cpOrderConvention && isAntiParticle ) conjThis(); + std::stable_sort( m_daughters.begin(), m_daughters.end(), [](const auto& A, const auto& B) { return *A < *B; } ); + if( m_cpOrderConvention && isAntiParticle ) conjThis(); m_uniqueString = makeUniqueString(); } + +void Particle::conjThis() +{ + if( m_props->hasDistinctAnti() ) + m_props = ParticlePropertiesList::get( -m_props->pdgID(), false); + for(unsigned i = 0 ; i != m_daughters.size(); ++i) m_daughters[i]->conjThis(); +} + Particle Particle::conj( bool invertHead , bool reorder ) { Particle cp(*this); @@ -689,11 +686,20 @@ void Particle::setLineshape( const std::string& lineshape ) m_lineshape = lineshape; m_uniqueString = makeUniqueString(); } + int Particle::finalStateParity() const { - int lpart = ( m_orbital % 2 == 0 ? 1 : -1 ); - for ( auto& d : m_daughters ) lpart *= d->parity(); - return lpart; + if( m_daughters.size() == 0) return 1; + if( m_daughters.size() == 1) return m_daughters[0]->finalStateParity(); /// forward through quasiparticles + if( m_daughters.size() == 2){ + int f = spin() - ( m_orbital + daughter(0)->spin() + daughter(1)->spin() ); + int lpart = (f % 2 == 0 ? 1 : -1); + for( auto& d : m_daughters ) lpart *= d->finalStateParity(); + return lpart; + } + WARNING("> 2 body vertices may require special considerations when conjugating, returning 1"); + return 1; + } bool Particle::conservesParity( unsigned int L ) const @@ -705,6 +711,7 @@ std::string Particle::topologicalString() const { return std::accumulate( m_daughters.begin(), m_daughters.end(), std::string(""), [](auto& s, auto& d){ return s+d->props()->J() ; } ); } + const ParticleProperties* Particle::props() const { return m_props; } bool Particle::isHead() const { return m_isHead; } bool Particle::isWeakDecay() const { return quarks() == daughterQuarks(); } @@ -732,6 +739,7 @@ void Particle::setDaughter( const Particle& particle, const unsigned int& index } std::vector> Particle::daughters() const { return m_daughters; } + bool Particle::operator<( const Particle& other ) { if ( spin() != other.spin() ) return spin() > other.spin(); @@ -797,21 +805,16 @@ unsigned int Particle::matches( const Particle& other ) const std::string Particle::decayDescriptor() const { return m_uniqueString ; } -int Particle::quasiCP() const +int Particle::CP() const { - if( m_daughters.size() == 1 ) return m_daughters[0]->quasiCP(); - int prod = m_props->C() == 0 ? 1 : m_props->C() ; - if( m_daughters.size() == 0 && m_props->C() != 0 ) - prod *= std::pow( -1, 0.5 * double(m_props->twoSpin()) ); - prod *= ( m_orbital % 2 == 0 ? 1 : -1 ); - for( auto& d : m_daughters ) prod *= d->quasiCP() ; - return prod; + return C() * finalStateParity(); } int Particle::C() const { - auto prod = ( props()->C() == 0 ? 1 : props()->C() ); - for( auto& d : m_daughters ) prod *= d->C(); + if( m_daughters.size() == 1 ) return m_daughters[0]->C(); + int prod = 1; + for( auto& d : m_daughters ) prod *= ( d->props()->C() == 0 ? 1 : d->props()->C() ) * d->C(); return prod; } diff --git a/src/ParticleProperties.cpp b/src/ParticleProperties.cpp index a48d496b0ff..20617a3b91b 100644 --- a/src/ParticleProperties.cpp +++ b/src/ParticleProperties.cpp @@ -65,7 +65,7 @@ ParticleProperties::ParticleProperties( const std::string& pdg_string ) : m_netQ m_status = s[15][0]; m_name = s[16]; m_quarks = s[17]; - m_Aformat = s[11][0]; + m_Aformat = s[11].size() == 1 ? s[11][0] : ' '; m_chargeString = s[13]; m_netQuarkContent = QuarkContent( m_quarks ); bool spin_status = 1; diff --git a/src/TreePhaseSpace.cpp b/src/TreePhaseSpace.cpp index 536a41200f4..9eeb6529e44 100644 --- a/src/TreePhaseSpace.cpp +++ b/src/TreePhaseSpace.cpp @@ -43,23 +43,45 @@ TreePhaseSpace::TreePhaseSpace(const std::vector& decayChains, const E } setRandom(rndm); } + for( auto& w : m_weights ) w /= double(m_weights.size()); m_dice = std::discrete_distribution<>(m_weights.begin(), m_weights.end()); } Event TreePhaseSpace::makeEvent( const unsigned& cacheSize ) { - double w = 0; - unsigned j = 0 ; - do { - j = m_dice(m_gen); - m_top[j].generate(); - w = m_top[j].weight(); - } while( w < m_rand->Rndm() ); + unsigned j = m_dice(m_gen); + m_top[j].generate(); auto event = m_top[j].event(m_type.size(), cacheSize); - event.setGenPdf(genPdf(event)); + event.setGenPdf(genPdf(event) / m_top[j].weight()); + m_generatorRecord.push_back(j); return event; } +void TreePhaseSpace::provideEfficiencyReport(const std::vector& report) +{ + if( report.size() != m_generatorRecord.size() ) + { + WARNING("Report does not match size of generator record..."); + return; + } + std::vector counters( m_top.size() ); + std::vector totals ( m_top.size() ); + unsigned counter = 0; + for( unsigned i = 0 ; i != report.size(); ++i ) + { + counters[m_generatorRecord[i]] += report[i]; + totals[m_generatorRecord[i]] ++; + counter += report[i]; + } + for( unsigned i = 0 ; i != m_top.size(); ++i ) + { + INFO( m_top[i].particle.decayDescriptor() << " " << counters[i] << " / " << totals[i] ); + m_weights[i] = double( counters[i] ) / double( counter ); + } + m_dice = std::discrete_distribution<>(m_weights.begin(), m_weights.end()); + m_generatorRecord.clear(); +} + double rho( const double& s, const double& s1, const double& s2) { return sqrt( 1 - 2 * (s1+s2)/s + (s1-s2)*(s1-s2) /(s*s) ); @@ -95,7 +117,6 @@ TreePhaseSpace::Vertex::Vertex(const Particle& particle, const double& min, cons if( index != 999 ) indices = {index}; phiMin = atan((min*min - bwMass*bwMass)/(bwMass*bwWidth)); phiMax = atan((max*max - bwMass*bwMass)/(bwMass*bwWidth)); -// if( isBW ) INFO( min << " ΔΦ= " << phiMax - phiMin << " " << bwMass << " " << bwWidth << " E= [" << max*max <<", " << min*min << "]" ); } double TreePhaseSpace::Vertex::p() const @@ -121,7 +142,7 @@ double TreePhaseSpace::Vertex::weight() const if( left == nullptr || right == nullptr ) return 1.0; double w = sqrt(s) - sqrt(left->s) - sqrt(right->s) > 0; if( w == 0 ) return 0; - w *= rho(s, left->s, right->s) / rhoMax; + w *= rho(s, left->s, right->s); w *= left -> weight(); w *= right -> weight(); return w; @@ -154,8 +175,10 @@ void TreePhaseSpace::Vertex::generate() void TreePhaseSpace::Vertex::print(const unsigned& offset) const { double rhoc = ( left != nullptr && right != nullptr ? rho(s,left->s,right->s) : rhoMax ); - if( isStable ) INFO( std::string(offset,' ') << particle.name() << " [" << vectorToString(indices, ", ") << "] → [" << min << "], ϱ' = " << rhoMax << ", s = " << s << ", ϱ = " << rhoc << " w = " << weight() ); - else INFO( std::string(offset,' ') << particle.name() << " [" << vectorToString(indices, ", ") << "] → [" << min << ", " << max << "] ϱ' =" << rhoMax << ", s = " << s << ", ϱ = " << rhoc << " w = " << weight() ); + if( isStable ) + INFO( std::string(offset,' ') << particle.name() << " [" << vectorToString(indices, ", ") << "] → [" << min << "], ϱ' = " << rhoMax << ", s = " << s << ", ϱ = " << rhoc << " w = " << maxWeight() ); + else + INFO( std::string(offset,' ') << particle.name() << " [" << vectorToString(indices, ", ") << "] → [" << min << ", " << max << "] ϱ' =" << rhoMax << ", s = " << s << ", ϱ = " << rhoc << " w = " << maxWeight() ); if( left != nullptr ) left -> print( offset + 4 ); if( right != nullptr ) right -> print( offset + 4 ); } @@ -175,27 +198,28 @@ void TreePhaseSpace::Vertex::place(Event& event) Event TreePhaseSpace::Vertex::event(const unsigned& eventSize, const unsigned& cacheSize) { Event output(4 * eventSize, cacheSize); - generate_full_event_description( TLorentzVector(0,0,0,sqrt(s)) ); + mom.SetXYZT(0,0,0,sqrt(s)); + generateFullEvent(); place(output); return output; } -void TreePhaseSpace::Vertex::generate_full_event_description(const TLorentzVector& parentVector) +void TreePhaseSpace::Vertex::generateFullEvent() { - mom = parentVector; + if( left == nullptr || right == nullptr ) return; double cosTheta = 2 * rand->Rndm() - 1; double sinTheta = sqrt( 1 - cosTheta * cosTheta ); double angY = 2 * M_PI * rand->Rndm(); double cosPhi = cos(angY); double sinPhi = sin(angY); - if( left == nullptr || right == nullptr ) return; double pf = p(); - TLorentzVector lvThisFrame( pf*sinTheta*cosPhi, pf*sinTheta*sinPhi, pf*cosTheta, sqrt(left->s + pf*pf) ); - TLorentzVector rvThisFrame( -pf*sinTheta*cosPhi, -pf*sinTheta*sinPhi, -pf*cosTheta, sqrt(right->s + pf*pf) ); - lvThisFrame.Boost( parentVector.BoostVector() ); - rvThisFrame.Boost( parentVector.BoostVector() ); - left -> generate_full_event_description(lvThisFrame); - right -> generate_full_event_description(rvThisFrame); + left -> mom.SetXYZT( pf*sinTheta*cosPhi, pf*sinTheta*sinPhi, pf*cosTheta, sqrt(left->s + pf*pf) ); + left -> mom.Boost( mom.BoostVector() ); + left -> generateFullEvent(); + + right -> mom.SetXYZT( -pf*sinTheta*cosPhi, -pf*sinTheta*sinPhi, -pf*cosTheta, sqrt(right->s + pf*pf) ); + right -> mom.Boost( mom.BoostVector() ); + right -> generateFullEvent(); } void TreePhaseSpace::Vertex::setRhoMax() @@ -256,7 +280,8 @@ EventType TreePhaseSpace::eventType() const double TreePhaseSpace::genPdf(const Event& event) const { double genPdf = 0; - for( auto& channel : m_top ) genPdf += channel.genPdf(event) / channel.weightMax; // / channel->w; + for( unsigned i = 0; i != m_top.size(); ++i ) + genPdf += m_weights[i] * m_top[i].genPdf(event); // / channel.weightMax; // / channel->w; return genPdf; } diff --git a/src/Utilities.cpp b/src/Utilities.cpp index 66e359d3546..4b61ec20d22 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -108,6 +108,13 @@ std::string AmpGen::replaceAll( const std::string& input, const std::string& toR return output; } +std::string AmpGen::replaceAll( const std::string& input, const std::vector>& rules ) +{ + std::string output = input; + for( auto& rule : rules ) output = replaceAll(output, rule.first, rule.second); + return output; +} + // extracts tree structures of the form X{Y,Z,A} // where Y and Z and A are also tree elements, by finding // the matching delimiter and the Z, A elements. diff --git a/src/Vertex.cpp b/src/Vertex.cpp index 053762c60da..317810da785 100644 --- a/src/Vertex.cpp +++ b/src/Vertex.cpp @@ -169,7 +169,7 @@ DEFINE_VERTEX( V_VS_P ) } -DEFINE_VERTEX( V_VS_S ){ return Spin1Projector(P)(mu,nu) * V1(-nu) * V2[0]; } +DEFINE_VERTEX( V_VS_S ){ auto S = Spin1Projector(P)(mu,nu) * V1(-nu) * V2[0]; ADD_DEBUG_TENSOR(S,db); return S; } DEFINE_VERTEX( V_VS_D ) { @@ -293,6 +293,30 @@ DEFINE_VERTEX( f_Vf_S1 ) return proj( a, b ) * vSlash(b,c) * V2(c); } +DEFINE_VERTEX( f_Vf_SL ) +{ + Tensor proj = Spin1hProjector(P); + return proj(a, b) * Gamma4Vec()(mu,b,c) * ( Identity(4) - Gamma[4] )(c,d)* V2(d) * V1(-mu); +} + +DEFINE_VERTEX( f_Vf_SR ) +{ + Tensor proj = Spin1hProjector(P); + return proj(a, b) * Gamma4Vec()(mu,b,c) * ( Identity(4) + Gamma[4] )(c,d)* V2(d) * V1(-mu); +} + +DEFINE_VERTEX( f_fS_SR ) +{ + Tensor proj = Spin1hProjector(P); + return proj(a, b) * ( Identity(4) - Gamma[4] )(b,c)* V2(c); +} + + +DEFINE_VERTEX( f_fS_SR ) +{ + Tensor proj = Spin1hProjector(P); + return proj(a, b) * ( Identity(4) + Gamma[4] )(b,c)* V2(c); +} DEFINE_VERTEX( f_fS_S1 ){ return Spin1hProjector(P)(a,b) * Gamma[4](b,c) * V1(c) * V2[0];} diff --git a/src/Wigner.cpp b/src/Wigner.cpp index 5a6bd9b454a..3159d43f5b5 100644 --- a/src/Wigner.cpp +++ b/src/Wigner.cpp @@ -238,7 +238,6 @@ Expression AmpGen::helicityAmplitude(const Particle& particle, if( NamedParameter("helicityAmplitude::NoSpinAlign", false ) ) return 2*Mz == particle.polState(); auto mzSpinor = basisSpinor( 2*Mz, particle.props()->pdgID() ); auto mzSpinorInLab = inverseMyTransform( mzSpinor, Transform::Representation::Bispinor ); - // lets just get the diagonal part // mzSpinorInLab.st(); ADD_DEBUG(Bar(mzSpinorInLab)(a)*labPol(a), db ); return make_cse( Bar(mzSpinorInLab)(a)*labPol(a) ); From 212f548d6ba182baae1ba113cf322018e3ba8c8b Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 25 Nov 2019 09:05:24 +0100 Subject: [PATCH 109/250] Changed CP conjugation behaviour to give expressions, rather than new free parameters and move to separate header / object --- AmpGen/AddCPConjugate.h | 6 +++ AmpGen/MinuitExpression.h | 6 +-- apps/ConvertToSourceCode.cpp | 35 +-------------- apps/Debugger.cpp | 87 ++---------------------------------- apps/Generator.cpp | 36 +-------------- examples/QcGenerator.cpp | 6 +-- src/AddCPConjugate.cpp | 50 +++++++++++++++++++++ src/MinuitExpression.cpp | 7 +++ src/Vertex.cpp | 2 +- 9 files changed, 76 insertions(+), 159 deletions(-) create mode 100644 AmpGen/AddCPConjugate.h create mode 100644 src/AddCPConjugate.cpp diff --git a/AmpGen/AddCPConjugate.h b/AmpGen/AddCPConjugate.h new file mode 100644 index 00000000000..40bb9011540 --- /dev/null +++ b/AmpGen/AddCPConjugate.h @@ -0,0 +1,6 @@ + +namespace AmpGen { + class MinuitParameterSet; + + void AddCPConjugate(MinuitParameterSet&); +} diff --git a/AmpGen/MinuitExpression.h b/AmpGen/MinuitExpression.h index 0e4dde4ac93..159abc5e0d8 100644 --- a/AmpGen/MinuitExpression.h +++ b/AmpGen/MinuitExpression.h @@ -15,13 +15,13 @@ namespace AmpGen class MinuitExpression : public MinuitParameter { public: - MinuitExpression( const std::vector& tokens, MinuitParameterSet* mps ); + MinuitExpression(const std::vector& tokens, MinuitParameterSet* mps ); + MinuitExpression(const std::string& name, const Expression& expression); double mean() const override; complex_t getVal() const; Expression expression() const { return m_expression; } operator double() const override; - ~MinuitExpression() override; - + ~MinuitExpression() override; private: Expression m_expression; }; diff --git a/apps/ConvertToSourceCode.cpp b/apps/ConvertToSourceCode.cpp index 60019f56a05..7e476408153 100644 --- a/apps/ConvertToSourceCode.cpp +++ b/apps/ConvertToSourceCode.cpp @@ -15,6 +15,7 @@ #include "AmpGen/ThreadPool.h" #include "AmpGen/Particle.h" #include "AmpGen/ParticlePropertiesList.h" +#include "AmpGen/AddCPConjugate.h" #include "TRandom3.h" @@ -68,38 +69,6 @@ void create_integration_tests(T& pdf, unit_tests.close(); } -void invert( MinuitParameter* param, MinuitParameterSet& mps ) -{ - const std::string name = param->name(); - size_t pos = 0; - std::string new_name = name; - int sgn = 1; - std::string cartOrPolar = NamedParameter("CouplingConstant::Coordinates" ,"cartesian"); - - if( name.find("::") != std::string::npos ){ - pos = name.find("::"); - auto props = AmpGen::ParticlePropertiesList::get( name.substr(0,pos), true ); - if( props != 0 ) new_name = props->anti().name() + name.substr(pos); - } - else { - auto tokens=split(name,'_'); - std::string reOrIm = *tokens.rbegin(); - std::string name = tokens[0]; - if ( reOrIm == "Re" || reOrIm == "Im" ){ - Particle test = Particle(name).conj(); - if( cartOrPolar == "polar" ) sgn = reOrIm == "Re" ? test.CP() : 1; - if( cartOrPolar == "cartesian" ) sgn = test.CP(); - new_name = test.uniqueString() +"_"+reOrIm; - } - else if( tokens.size() == 2 ) { - auto props = AmpGen::ParticlePropertiesList::get( name ); - if( props != 0 ) new_name = props->anti().name() + "_" + tokens[1]; - } - } - mps.rename( param->name(), new_name ); - if( sgn == -1 ){ param->setInit( -1*param->mean() ) ; param->setCurrentFitVal( -1 * param->mean() );} -} - template void generate_source(T& pdf, EventList& normEvents, const std::string& sourceFile, MinuitParameterSet& mps, const double& sf) { bool normalise = NamedParameter("Normalise",true); @@ -147,7 +116,7 @@ int main( int argc, char** argv ) if ( NamedParameter( "conj", false ) == true ) { eventType = eventType.conj(true); - for ( auto& param : MPS ) invert( param, MPS ); + AddCPConjugate(MPS); } Generator phsp( eventType ); TRandom3 rnd; diff --git a/apps/Debugger.cpp b/apps/Debugger.cpp index 6e3b73a58fa..a440aab9247 100644 --- a/apps/Debugger.cpp +++ b/apps/Debugger.cpp @@ -20,6 +20,7 @@ #include "AmpGen/ParticlePropertiesList.h" #include "AmpGen/Utilities.h" #include "TRandom3.h" +#include "AmpGen/AddCPConjugate.h" #ifdef _OPENMP #include @@ -33,6 +34,7 @@ #include "AmpGen/NamedParameter.h" #include "AmpGen/PolarisedSum.h" + using namespace AmpGen; void invertParity( Event& event, const size_t& nParticles) @@ -45,89 +47,6 @@ void invertParity( Event& event, const size_t& nParticles) } } -void invert( MinuitParameter* param, MinuitParameterSet& mps ) -{ - const std::string name = param->name(); - size_t pos = 0; - std::string new_name = name; - int sgn = 1; - std::string cartOrPolar = NamedParameter("CouplingConstant::Coordinates" ,"cartesian"); - if( name.find("::") != std::string::npos ){ - pos = name.find("::"); - auto props = AmpGen::ParticlePropertiesList::get( name.substr(0,pos), true ); - if( props != 0 ) new_name = props->anti().name() + name.substr(pos); - } - else { - auto tokens=split(name,'_'); - std::string reOrIm = *tokens.rbegin(); - std::string name = tokens[0]; - if ( reOrIm == "Re" || reOrIm == "Im" ){ - Particle test = Particle(name).conj(); - if( cartOrPolar == "polar" ) sgn = reOrIm == "Re" ? test.CP() : 1; - if( cartOrPolar == "cartesian" ) sgn = test.CP(); - new_name = test.uniqueString() +"_"+reOrIm; - } - else if( tokens.size() == 2 ) { - auto props = AmpGen::ParticlePropertiesList::get( name ); - if( props != 0 ) new_name = props->anti().name() + "_" + tokens[1]; - } - } - if( mps.rename( param->name(), new_name ) && sgn == -1 ) - param->setCurrentFitVal( -1 * param->mean() ); -} - -void add_CP_conjugate( MinuitParameterSet& mps ) -{ - std::vector tmp; - std::string cartOrPolar = NamedParameter("CouplingConstant::Coordinates" ,"cartesian"); - for( auto& param : mps ){ - const std::string name = param->name(); - size_t pos=0; - std::string new_name = name; - int sgn=1; - if( name.find("::") != std::string::npos ){ - pos = name.find("::"); - auto props = AmpGen::ParticlePropertiesList::get( name.substr(0,pos), true ); - if( props != 0 ) new_name = props->anti().name() + name.substr(pos); - } - else { - auto tokens=split(name,'_'); - std::string reOrIm = *tokens.rbegin(); - std::string name = tokens[0]; - if ( reOrIm == "Re" || reOrIm == "Im" ){ - Particle test = Particle(name).conj(); - if( cartOrPolar == "polar" ) sgn = reOrIm == "Re" ? test.CP() : 1; - if( cartOrPolar == "cartesian" ) sgn = test.CP(); - new_name = test.uniqueString() +"_"+reOrIm; - } - else if( tokens.size() == 2 ) { - auto props = AmpGen::ParticlePropertiesList::get( name ); - if( props != 0 ) new_name = props->anti().name() + "_" + tokens[1]; - } - } - if( mps.find( new_name ) == nullptr ) tmp.push_back( new MinuitParameter(new_name, Flag::Free, sgn * param->mean(), param->err(), 0, 0)); - } - for( auto& p : tmp ){ - INFO("Adding parameter: " << p->name() ); - mps.add( p ); - } -} - -/* -template void print( const Event& event, const MatrixElements& matrixElements, bool verbose ) -{ - for ( auto& mE : matrixElements ) { - INFO( mE.decayDescriptor() << " " << mE.coupling() ); - if ( verbose ) { - for ( auto& term : mE.coupling ) { - INFO( "--> " << term.particle().decayDescriptor() << " = " << term() ); - } - mE.amp.debug( event.address() ); - } - } -} -*/ - template < class FCN > void debug( FCN& sig, EventList& accepted, bool verbose, TRandom3* rndm, MinuitParameterSet& mps ){ INFO("Debugging: "); sig.setEvents( accepted ); @@ -162,7 +81,7 @@ int main( int argc, char** argv ) { eventType = eventType.conj(); INFO( eventType ); - add_CP_conjugate(MPS); + AddCPConjugate(MPS); } INFO( "EventType = " << eventType ); diff --git a/apps/Generator.cpp b/apps/Generator.cpp index faa876dbeb0..ef6d3a566da 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -29,43 +29,12 @@ #include "AmpGen/TreePhaseSpace.h" #include "AmpGen/enum.h" #include "AmpGen/ParticlePropertiesList.h" +#include "AmpGen/AddCPConjugate.h" using namespace AmpGen; namespace AmpGen { make_enum(generatorType, CoherentSum, PolarisedSum, FixedLib, RGenerator, TreePhaseSpace) } -void invert( MinuitParameter* param, MinuitParameterSet& mps ) -{ - const std::string name = param->name(); - size_t pos = 0; - std::string new_name = name; - int sgn = 1; - std::string cartOrPolar = NamedParameter("CouplingConstant::Coordinates" ,"cartesian"); - - if( name.find("::") != std::string::npos ){ - pos = name.find("::"); - auto props = ParticlePropertiesList::get( name.substr(0,pos), true ); - if( props != 0 ) new_name = props->anti().name() + name.substr(pos); - } - else { - auto tokens=split(name,'_'); - std::string reOrIm = *tokens.rbegin(); - std::string name = tokens[0]; - if ( reOrIm == "Re" || reOrIm == "Im" ){ - Particle test = Particle(name).conj(); - if( cartOrPolar == "polar" ) sgn = reOrIm == "Re" ? test.CP() : 1; - if( cartOrPolar == "cartesian" ) sgn = test.CP(); - new_name = test.uniqueString() +"_"+reOrIm; - } - else if( tokens.size() == 2 ) { - auto props = ParticlePropertiesList::get( name ); - if( props != 0 ) new_name = props->anti().name() + "_" + tokens[1]; - } - } - if( mps.rename( param->name(), new_name ) && sgn == -1 ) - param->setCurrentFitVal( -1 * param->mean() ); -} - struct FixedLibPDF { void* lib = {nullptr}; AmpGen::DynamicFCN PDF; @@ -145,10 +114,9 @@ int main( int argc, char** argv ) if ( NamedParameter( "conj", false ) == true ) { eventType = eventType.conj(); INFO( eventType ); - for ( auto& param : MPS ) invert( param, MPS ); + AddCPConjugate(MPS); } - INFO("Generating time-dependence? " << eventType.isTimeDependent() ); EventList accepted( eventType ); diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp index 51f0b3ff0a0..4ca7fec3cf6 100644 --- a/examples/QcGenerator.cpp +++ b/examples/QcGenerator.cpp @@ -7,7 +7,7 @@ #include "AmpGen/ProfileClock.h" #include "AmpGen/ParticlePropertiesList.h" #include "AmpGen/MinuitParameterSet.h" - +#include "AmpGen/AddCPConjugate.h" #include #include #include @@ -85,8 +85,6 @@ class DTYieldCalculator { std::map efficiencies = {getKeyed("Efficiencies")}; }; -void add_CP_conjugate( MinuitParameterSet& mps ); - template struct normalised_pdf { PDF pdf; complex_t norm; @@ -266,7 +264,7 @@ int main( int argc, char** argv ) #endif MinuitParameterSet MPS; MPS.loadFromStream(); - add_CP_conjugate( MPS ); + AddCPConjugate(MPS); EventType signalType( pNames ); TFile* f = TFile::Open( output.c_str() ,"RECREATE"); auto yc = DTYieldCalculator(crossSection); diff --git a/src/AddCPConjugate.cpp b/src/AddCPConjugate.cpp new file mode 100644 index 00000000000..04a960d69ed --- /dev/null +++ b/src/AddCPConjugate.cpp @@ -0,0 +1,50 @@ +#include +#include + +#include "AmpGen/AddCPConjugate.h" +#include "AmpGen/MinuitParameterSet.h" +#include "AmpGen/NamedParameter.h" +#include "AmpGen/ExpressionParser.h" +#include "AmpGen/MinuitExpression.h" +#include "AmpGen/Particle.h" +#include "AmpGen/ParticlePropertiesList.h" + +using namespace AmpGen; + +void AmpGen::AddCPConjugate( MinuitParameterSet& mps ) +{ + std::vector tmp; + std::string cartOrPolar = NamedParameter("CouplingConstant::Coordinates" ,"cartesian"); + for( auto& param : mps ){ + const std::string name = param->name(); + size_t pos=0; + std::string new_name = name; + int sgn=1; + if( name.find("::") != std::string::npos ){ + pos = name.find("::"); + auto props = AmpGen::ParticlePropertiesList::get( name.substr(0,pos), true ); + if( props != 0 ) new_name = props->anti().name() + name.substr(pos); + } + else { + auto tokens=split(name,'_'); + std::string reOrIm = *tokens.rbegin(); + std::string name = tokens[0]; + if ( reOrIm == "Re" || reOrIm == "Im" ){ + Particle test = Particle(name).conj(); + if( cartOrPolar == "polar" ) sgn = reOrIm == "Re" ? test.CP() : 1; + if( cartOrPolar == "cartesian" ) sgn = test.CP(); + new_name = test.uniqueString() +"_"+reOrIm; + } + else if( tokens.size() == 2 ) { + auto props = AmpGen::ParticlePropertiesList::get( name ); + if( props != 0 ) new_name = props->anti().name() + "_" + tokens[1]; + } + } + if( mps.find( new_name ) == nullptr ) + tmp.push_back( new MinuitExpression(new_name, sgn * MinuitParameterLink(param) )) ; + } + for( auto& p : tmp ){ + INFO("Adding parameter: " << p->name() ); + mps.add( p ); + } +} diff --git a/src/MinuitExpression.cpp b/src/MinuitExpression.cpp index 424ada7db59..d9f1c015ae1 100644 --- a/src/MinuitExpression.cpp +++ b/src/MinuitExpression.cpp @@ -16,6 +16,13 @@ MinuitExpression::MinuitExpression( const std::vector& tokens, Minu fix(); } +MinuitExpression::MinuitExpression(const std::string& name, const Expression& expression) +{ + setName(name); + m_expression = expression; + fix(); +} + double MinuitExpression::mean() const { return std::real(getVal()); } complex_t MinuitExpression::getVal() const { return m_expression(); } MinuitExpression::operator double() const { return std::real(getVal()); } diff --git a/src/Vertex.cpp b/src/Vertex.cpp index 317810da785..4af6ab7c40d 100644 --- a/src/Vertex.cpp +++ b/src/Vertex.cpp @@ -305,7 +305,7 @@ DEFINE_VERTEX( f_Vf_SR ) return proj(a, b) * Gamma4Vec()(mu,b,c) * ( Identity(4) + Gamma[4] )(c,d)* V2(d) * V1(-mu); } -DEFINE_VERTEX( f_fS_SR ) +DEFINE_VERTEX( f_fS_SL ) { Tensor proj = Spin1hProjector(P); return proj(a, b) * ( Identity(4) - Gamma[4] )(b,c)* V2(c); From abc87739b460daaaa1af5672b26832b31cdc5e1c Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 25 Nov 2019 09:31:56 +0100 Subject: [PATCH 110/250] Remove some noise from AddCPConjugate + AmplitudeRules --- src/AddCPConjugate.cpp | 7 ++----- src/AmplitudeRules.cpp | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/AddCPConjugate.cpp b/src/AddCPConjugate.cpp index 04a960d69ed..29252cc2c8f 100644 --- a/src/AddCPConjugate.cpp +++ b/src/AddCPConjugate.cpp @@ -36,15 +36,12 @@ void AmpGen::AddCPConjugate( MinuitParameterSet& mps ) new_name = test.uniqueString() +"_"+reOrIm; } else if( tokens.size() == 2 ) { - auto props = AmpGen::ParticlePropertiesList::get( name ); + auto props = AmpGen::ParticlePropertiesList::get(name, true); if( props != 0 ) new_name = props->anti().name() + "_" + tokens[1]; } } if( mps.find( new_name ) == nullptr ) tmp.push_back( new MinuitExpression(new_name, sgn * MinuitParameterLink(param) )) ; } - for( auto& p : tmp ){ - INFO("Adding parameter: " << p->name() ); - mps.add( p ); - } + for( auto& p : tmp ) mps.add( p ); } diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index c2d81d2e314..cae67717ef8 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -73,7 +73,7 @@ AmplitudeRules::AmplitudeRules( const MinuitParameterSet& mps ) bool isCoupling = Particle::isValidDecayDescriptor( it_re->name() ); if( isCoupling ){ MinuitExpression* expression = dynamic_cast( it_re ); - INFO("Constructing: " << expression << " " << it_re->name() ); + DEBUG("Constructing: " << expression << " " << it_re->name() ); if( expression != nullptr ){ Coupling p(expression); m_rules[p.head()].emplace_back(p); From 042c2e460165893d956373086baafb93b5184063 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 28 Nov 2019 10:19:42 +0100 Subject: [PATCH 111/250] Fix mising thing that was broken, add unstable initial states to tree phase space, fix CP of K0s --- AmpGen/ParticleProperties.h | 6 ++++-- options/mass_width.csv | 4 ++-- src/Particle.cpp | 7 +++---- src/ParticleProperties.cpp | 1 + src/PolarisedSum.cpp | 11 ++++++++++- src/TreePhaseSpace.cpp | 3 ++- 6 files changed, 22 insertions(+), 10 deletions(-) diff --git a/AmpGen/ParticleProperties.h b/AmpGen/ParticleProperties.h index d68ac653334..8ca7c45cb1b 100644 --- a/AmpGen/ParticleProperties.h +++ b/AmpGen/ParticleProperties.h @@ -57,7 +57,9 @@ namespace AmpGen const QuarkContent& netQuarkContent() const { return m_netQuarkContent; } ///< Returns the particle's quark content void setLabel( const std::string& label ) { m_texName = label; } ///< Set the LaTeX label of the particle - void setName( const std::string& name ) { m_name = name; } ///< Set the name of the particle + void setName( const std::string& name ) { + m_customName = true; + m_name = name; } ///< Set the name of the particle void print( std::ostream& out = std::cout ) const; @@ -97,7 +99,7 @@ namespace AmpGen char m_status; ///< status (estalished or not etc) QuarkContent m_netQuarkContent; ///< The quark content of the state (uD, uud etc.) bool m_isValid; ///< Flag to check whether the ParticleProperties have configured correctly - + bool m_customName = {false}; ///< Flag to make custom name void antiQuarks(); void antiCharge(); int chargeFromString( const std::string& ch, bool& status ) const; diff --git a/options/mass_width.csv b/options/mass_width.csv index 50cacb48a00..4d32b4ebd45 100644 --- a/options/mass_width.csv +++ b/options/mass_width.csv @@ -316,8 +316,8 @@ 3.350E+03 ,2.2E+01,2.8E+01,7.0E+01 ,6.0E+01,5.0E+01,? ,?,? ,?,?, , , 0, ,F,X(3350) ,?? 4.93677E+02 ,1.6E-02,1.6E-02,5.352E-14 ,9.0E-17,9.0E-17,1/2, ,0 ,-, ,B, 321, +, ,R,K ,uS 4.97614E+02 ,2.4E-02,2.4E-02,-1 ,-1 ,-1 ,1/2, ,0 ,-, ,F, 311, 0, ,R,K ,dS -4.97614E+02 ,2.4E-02,2.4E-02,7.397E-12 ,4.0E-15,4.0E-15,1/2, ,0 ,-, , , 310, 0, ,R,K0S ,p(dS)+q(Ds) -4.97614E+02 ,2.4E-02,2.4E-02,1.295E-14 ,5.0E-17,5.0E-17,1/2, ,0 ,-, , , 130, 0, ,R,K0L ,p(dS)-q(Ds) +4.97614E+02 ,2.4E-02,2.4E-02,7.397E-12 ,4.0E-15,4.0E-15,1/2, ,0 ,-,-, , 310, 0, ,R,K0S ,p(dS)+q(Ds) +4.97614E+02 ,2.4E-02,2.4E-02,1.295E-14 ,5.0E-17,5.0E-17,1/2, ,0 ,-,+, , 130, 0, ,R,K0L ,p(dS)-q(Ds) 6.7E+02 ,4.0E+01,4.0E+01,5.50E+02 ,3.4E+01,3.4E+01,1/2, ,0 ,+, ,F,9000321, +, ,S,K(0)*(800) ,uS 6.7E+02 ,4.0E+01,4.0E+01,5.50E+02 ,3.4E+01,3.4E+01,1/2, ,0 ,+, ,F,9000311, 0, ,S,K(0)*(800) ,dS 8.9166E+02 ,2.6E-01,2.6E-01,5.08E+01 ,9.0E-01,9.0E-01,1/2, ,1 ,-, ,F, 323, +, ,R,K*(892) ,uS diff --git a/src/Particle.cpp b/src/Particle.cpp index 0ce27e91570..fd7fc00fbc2 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -68,7 +68,6 @@ Particle::Particle( const std::string& decayString, const std::vectorname() ); std::vector hasUsedFinalState( finalStates.size(), 0 ); for ( auto d : fs ) { for ( unsigned int i = 0; i < finalStates.size(); ++i ) { @@ -697,9 +697,8 @@ int Particle::finalStateParity() const for( auto& d : m_daughters ) lpart *= d->finalStateParity(); return lpart; } - WARNING("> 2 body vertices may require special considerations when conjugating, returning 1"); - return 1; - + WARNING("> 2 body vertices may require special considerations when conjugating, returning (-1)^J"); + return pow(-1, spin() ); } bool Particle::conservesParity( unsigned int L ) const diff --git a/src/ParticleProperties.cpp b/src/ParticleProperties.cpp index 20617a3b91b..77d55d03b7e 100644 --- a/src/ParticleProperties.cpp +++ b/src/ParticleProperties.cpp @@ -120,6 +120,7 @@ ParticleProperties ParticleProperties::anti() const std::string ParticleProperties::name() const { + if( m_customName ) return m_name; std::string fullName = m_name; if ( m_pdgID < 0 && m_Aformat == 'F' ) fullName += "bar"; fullName += m_chargeString; diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index fc94b44c845..1b2cbe12c8f 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -92,6 +92,7 @@ std::vector PolarisedSum::polarisations( const std::string& name ) const auto props = *ParticlePropertiesList::get( name ); if( props.twoSpin() == 0 ) return {0}; if( props.twoSpin() == 1 ) return {1,-1}; + if( props.twoSpin() == 4 ) return {-2,1,0,1,2}; if( name == "gamma0" && props.twoSpin() == 2 ) return {1,-1}; if( name != "gamma0" && props.twoSpin() == 2 ) return {1,0,-1}; @@ -115,6 +116,14 @@ std::vector> PolarisedSum::polarisationOuterProduct(const std:: std::vector densityMatrix(const size_t& dim, const std::vector& pv ) { + INFO( "Dim = " << dim << ", " << pv.size() ); + if( dim != 2 || dim != 3 ) + { + std::vector rt(dim*dim); + for( unsigned i = 0 ; i != dim; ++i ) rt[ dim*i +i ] = 1; + return rt; + } + if( dim == 1 ) return {1.}; double px = pv[0]; double py = pv[1]; @@ -264,7 +273,7 @@ double PolarisedSum::norm() const return m_norm; } -complex_t PolarisedSum::norm(const size_t& i, const size_t& j, AmpGen::PolarisedSum::integrator* integ) +complex_t PolarisedSum::norm(const size_t& i, const size_t& j, PolarisedSum::integrator* integ) { auto ai = m_integIndex[i]; auto aj = m_integIndex[j]; diff --git a/src/TreePhaseSpace.cpp b/src/TreePhaseSpace.cpp index 9eeb6529e44..a6f0f25bbb7 100644 --- a/src/TreePhaseSpace.cpp +++ b/src/TreePhaseSpace.cpp @@ -240,7 +240,8 @@ TreePhaseSpace::Vertex TreePhaseSpace::Vertex::make(const Particle& particle, Tr if( decayProducts.size() == 1 ) return TreePhaseSpace::Vertex::make(*decayProducts[0], parent); if( decayProducts.size() == 2 ) { - TreePhaseSpace::Vertex vtx = (parent == nullptr) ? TreePhaseSpace::Vertex(particle, particle.mass(), particle.mass(), true) : TreePhaseSpace::Vertex(); + double G = particle.isQuasiStable() ? 0 : particle.props()->width() * 10; + TreePhaseSpace::Vertex vtx = (parent == nullptr) ? TreePhaseSpace::Vertex(particle, particle.mass() - G , particle.mass() + G, particle.isQuasiStable() ) : TreePhaseSpace::Vertex(); parent = ( parent == nullptr ) ? &vtx : parent; auto min_mass_1 = threshold(*decayProducts[0]); From 2fdbcf14f2547e4f4fda06839837eb7dd1d3fe7e Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 7 Jan 2020 11:02:35 +0100 Subject: [PATCH 112/250] Add states of ill-defined initial flavour to PolarisedSum --- AmpGen/CoherentSum.h | 5 +- AmpGen/EventList.h | 4 + AmpGen/EventType.h | 3 +- AmpGen/NamedParameter.h | 2 + AmpGen/Particle.h | 32 +++-- AmpGen/ParticleProperties.h | 4 + AmpGen/Plots.h | 11 +- AmpGen/PolarisedSum.h | 11 +- AmpGen/Projection.h | 11 +- AmpGen/Vertex.h | 2 + Standalone.cmake | 4 +- doc/release.notes | 1 + examples/FitterWithPolarisation.cpp | 4 +- examples/QcGenerator.cpp | 4 +- src/AddCPConjugate.cpp | 2 + src/AmplitudeRules.cpp | 2 +- src/CoherentSum.cpp | 20 +-- src/EventList.cpp | 9 +- src/EventType.cpp | 23 +++- src/Minimiser.cpp | 2 + src/Particle.cpp | 205 +++++++++++++++------------- src/ParticleProperties.cpp | 10 ++ src/PolarisedSum.cpp | 169 +++++++++++++---------- src/Projection.cpp | 5 +- src/TreePhaseSpace.cpp | 42 +++--- src/Vertex.cpp | 12 ++ test/test_NamedParameter.cpp | 4 +- 27 files changed, 354 insertions(+), 249 deletions(-) diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index a8e47dfe933..e9ba71b0cb9 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -19,6 +19,7 @@ #include "AmpGen/Types.h" #include "AmpGen/Event.h" #include "AmpGen/Projection.h" + //#include "AmpGen/functional/pdf.h" namespace AmpGen @@ -47,7 +48,7 @@ namespace AmpGen CoherentSum( const EventType& type, const AmpGen::MinuitParameterSet& mps, const std::string& prefix = "" ); virtual ~CoherentSum() = default; - AmplitudeRules protoAmplitudes() { return m_protoAmplitudes; } + AmplitudeRules protoAmplitudes() { return m_rules; } std::string prefix() const { return m_prefix; } TransitionMatrix operator[]( const size_t& index ) { return m_matrixElements[index]; } @@ -92,7 +93,7 @@ namespace AmpGen typedef Integrator<10> integrator; std::vector> m_matrixElements; ///< Vector of (expanded) matrix elements Bilinears m_normalisations; ///< Normalisation integrals - AmplitudeRules m_protoAmplitudes; ///< Proto amplitudes from user rule-set + AmplitudeRules m_rules; ///< Ruleset for the selected transition. integrator m_integrator; ///< Integral dispatch tool (with default unroll = 10) TransitionMatrix m_total; ///< Total Matrix Element EventList* m_events = {nullptr}; ///< Data events to evaluate PDF on diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index dd9ab8f9fd6..3291b2e305a 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -46,6 +46,10 @@ namespace AmpGen { loadFromFile( fname, ArgumentPack(args...) ); } + template < class ... ARGS > EventList( const std::string& fname, const ARGS&... args ) : EventList() + { + loadFromFile( fname, ArgumentPack(args...) ); + } template < class ... ARGS > EventList( const std::vector& fname, const EventType& evtType, const ARGS&... args ) : EventList(evtType) { for( auto& f : fname ) loadFromFile( f, ArgumentPack(args...) ); diff --git a/AmpGen/EventType.h b/AmpGen/EventType.h index d1f2168a684..d83dd26f815 100644 --- a/AmpGen/EventType.h +++ b/AmpGen/EventType.h @@ -70,9 +70,10 @@ namespace AmpGen std::vector m_particleNames; ///< names of decay products std::vector m_particleNamesPickled; ///< names of decay product pickled for ROOT std::vector m_particleMasses; ///< masses of decay products + std::vector m_ignore; ///< Flag to ignore particle when reading events, for invisible or tags bool m_timeDependent; ///< Flag to include a decay time as the last element in the event vector std::vector m_eventTypeExtensions; ///< extended event data - std::pair m_dim; ///< Rank of the relevant transition matrix + std::pair m_dim; ///< Rank of the relevant transition matrix bool m_alt_part_names; ///< alternative naming in ouput tree (e.g. Xi- pi+ pi+ becomes Xim pip0 pip1 rather than _1_Xi# _2_pi~ _3_pi~) }; std::ostream& operator<<( std::ostream& os, const EventType& type ); diff --git a/AmpGen/NamedParameter.h b/AmpGen/NamedParameter.h index a654e65cee0..374ff4b3fb5 100644 --- a/AmpGen/NamedParameter.h +++ b/AmpGen/NamedParameter.h @@ -106,6 +106,8 @@ namespace AmpGen operator T() const { return getVal(); } operator T() { return getVal(); } + template bool operator==(const G& other) const { return getVal() == other; } + template bool operator!=(const G& other) const { return getVal() != other; } const std::vector& getVector() const { return m_valueArray; } void setVal( const T& val, int i = 0 ) diff --git a/AmpGen/Particle.h b/AmpGen/Particle.h index 030315efc54..15577818f98 100644 --- a/AmpGen/Particle.h +++ b/AmpGen/Particle.h @@ -26,7 +26,8 @@ namespace stdx { #include "AmpGen/Expression.h" #include "AmpGen/Tensor.h" #include "AmpGen/QuarkContent.h" - +#include "AmpGen/NamedParameter.h" +#include "AmpGen/enum.h" namespace AmpGen { /** @class Particle @@ -94,6 +95,10 @@ namespace AmpGen Similar to other components of AmpGen, Particles will rarely be constructed in the C++ context, and will instead be instantiated dynamically at runtime from a user supplied options file. */ class ParticleProperties; + + declare_enum( spinFormalism, Covariant, Canonical ) + declare_enum( spinBasis , Dirac , Weyl ) + class Particle { public: @@ -128,9 +133,9 @@ namespace AmpGen /// Set the index'th daughter of this to particle. void setDaughter( const Particle& particle, const unsigned int& index ); - - /// Set the flag to say this - void setTop( bool state = true ); + + /// Set the parent particle for this particle + void setParent( const Particle* particle ); /// Set the index of this particle, i.e. where it is positioned in the event data structure. void setIndex( const unsigned int& index, const bool& setOri = false ); @@ -155,6 +160,7 @@ namespace AmpGen /// Set the polarisation state of this particle, which is twice the projection of the spin along the quantisation axis. void setPolarisationState( const int& state ); + void setPolarisationState( const std::vector& state); /// Returns the range of orbital angular momentum between the decay products std::pair orbitalRange( const bool& converseParity = true ) const; @@ -271,8 +277,8 @@ namespace AmpGen unsigned int matches( const Particle& other ) const; std::string makeUniqueString(); ///< Generate the decay descriptor for this decay. private: - const ParticleProperties* m_props = {nullptr}; ///< Particle Properties from the PDG std::string m_name = {""}; ///< Name of the particle + const ParticleProperties* m_props = {nullptr}; ///< Particle Properties from the PDG std::string m_lineshape = {"BW"}; ///< Propagator to use std::string m_uniqueString = {""}; ///< Unique string of particle tree int m_parity = {0}; ///< Intrinsic parity of particle @@ -282,20 +288,24 @@ namespace AmpGen unsigned m_orbital = {0}; ///< Orbital angular momentum between daughters unsigned m_spinConfigurationNumber = {0}; ///< Spin configuration quantum number 'S' unsigned m_minL = {0}; ///< Minimum orbital angular momentum - bool m_isHead = {true}; ///< Flag that particle is head of decay chain bool m_usesDefaultLineshape = {false}; ///< Flag to check if default shape is used bool m_isStateGood = {true}; ///< Flag to check the decay is well-formed std::vector> m_daughters; ///< Array of daughter particles std::vector m_modifiers; ///< Additional modifiers for amplitude - std::string m_spinFormalism = {""}; ///< Spin formalism to use for this particle (global) - std::string m_spinBasis = {""}; ///< Basis to use for external polarisations (global) - std::string m_defaultModifier = {""}; ///< Default Modifier to use (global) - bool m_cpOrderConvention = {false}; ///< Use modified particle ordering convention that should be more robust with respect to CP conjugation - + const Particle* m_parent = {nullptr}; ///< Pointer to the parent particle of this particle void pdgLookup(); ///< Lookup information from the PDG database (using ParticlePropertiesList) bool hasModifier( const std::string& modifier ) const; ///< Check if this particle has a given modifier std::string modifierString() const; ///< Re-generate modifier string used to create particle void sortDaughters(); ///< Recursively order the particle's decay products. + + NamedParameter m_spinFormalism = {"Particle::SpinFormalism" ,spinFormalism::Covariant, optionalHelpString("Formalism to use for spin calculations", { + {"Covariant", "[default] Covariant Tensor, based on Rarita-Schwinger constraints on the allowed covariant wavefunctions."} + , {"Canonical", "Canonical formulation, based on rotational properties of wavefunctions, i.e. Wigner D-matrices and Clebsch-Gordan for (L,S) expansion."} } ) }; + + NamedParameter m_spinBasis = {"Particle::SpinBasis", spinBasis::Dirac, optionalHelpString("Basis to use for calculating external polarisation tensors / spinors.", { + {"Dirac", "[default] Quantises along the z-axis"} + , {"Weyl" , "Quantises along the direction of motion"}} )}; + NamedParameter m_defaultModifier = {"Particle::DefaultModifier","", "Default modifier to use for lineshapes, for example to use normalised vs unnormalised Blatt-Weisskopf factors."}; }; std::ostream& operator<<( std::ostream& os, const Particle& particle ); } // namespace AmpGen diff --git a/AmpGen/ParticleProperties.h b/AmpGen/ParticleProperties.h index 8ca7c45cb1b..fc16668483f 100644 --- a/AmpGen/ParticleProperties.h +++ b/AmpGen/ParticleProperties.h @@ -54,6 +54,10 @@ namespace AmpGen bool isNonResonant() const; ///< Check is this is a nonresonant `quasi-particle' bool isFermion() const; ///< Check if the particle is a fermion, i.e. if the spin 1/2, 3/2, ... bool isBoson() const; ///< Check if the particle is a boson, i.e. if the spin 0, 1, 2... + bool isNeutrino() const; ///< Check if the particle is a neutrino + + bool isPhoton() const; ///< Check if the particle is a photon + const QuarkContent& netQuarkContent() const { return m_netQuarkContent; } ///< Returns the particle's quark content void setLabel( const std::string& label ) { m_texName = label; } ///< Set the LaTeX label of the particle diff --git a/AmpGen/Plots.h b/AmpGen/Plots.h index e21519cff8d..7f8c81388fa 100644 --- a/AmpGen/Plots.h +++ b/AmpGen/Plots.h @@ -23,18 +23,17 @@ namespace AmpGen template std::array getNorms( CoherentSum& fcn, BinnedIntegrator& bid ) { - std::array normalisations; for ( unsigned int i = 0; i < NBINS; ++i ) normalisations[i] = Bilinears( fcn.size(), fcn.size() ); - for ( unsigned int i = 0; i < fcn.size(); ++i ) { for ( unsigned int j = i; j < fcn.size(); ++j ) { - bid.addIntegral( fcn[i].amp, fcn[j].amp, [i, j, &normalisations]( const auto& val ) { - for ( unsigned int bin = 0; bin < NBINS; ++bin ) { + bid.addIntegral( fcn[i].amp, fcn[j].amp, [i, j, &normalisations]( const auto& val ) + { + for ( unsigned int bin = 0; bin < NBINS; ++bin ) { normalisations[bin].set( i, j, val[bin] ); if ( i != j ) normalisations[bin].set( j, i, std::conj( val[bin] ) ); - } - } ); + } + } ); } } bid.flush(); diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index 0ce4fa3b580..a60898c1aa7 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -69,22 +69,23 @@ namespace AmpGen real_t m_norm = {1}; EventList* m_events = {nullptr}; MinuitParameter* m_weightParam = {nullptr}; - const MinuitParameterSet* m_mps = {nullptr}; + MinuitParameterSet* m_mps = {nullptr}; double m_weight = {1}; std::vector m_pVector = {}; bool m_verbosity = {0}; bool m_debug = {0}; integrator m_integrator; std::vector m_norms; - std::vector> m_polStates; EventType m_eventType; std::string m_prefix = ""; std::vector m_rho; std::vector m_integIndex; - std::vector>> m_matrixElements; - CompiledExpression m_probExpression; AmplitudeRules m_rules; - std::vector> polarisationOuterProduct(const std::vector>&, const std::vector&) const; + std::pair m_dim; + std::vector>> m_matrixElements; + CompiledExpression m_probExpression; + + std::vector> indexProduct(const std::vector>&, const std::vector&) const; std::vector polarisations(const std::string&) const ; }; } // namespace AmpGen diff --git a/AmpGen/Projection.h b/AmpGen/Projection.h index ea0f02378ec..6f14beeaee0 100644 --- a/AmpGen/Projection.h +++ b/AmpGen/Projection.h @@ -8,7 +8,7 @@ #include "TH1D.h" #include "TH2D.h" -//#include "AmpGen/Event.h" +#include "AmpGen/ArgumentPack.h" class TH1D; class TH2D; @@ -30,9 +30,11 @@ namespace AmpGen Projection( const std::function& fcn, const std::string& name, const std::string& xAxisTitle, const size_t& nBins, const double& min, const double& max, const std::string& units = "" ); - const std::string name() const ; - double operator()( const Event& evt ) const ; - TH1D* operator()(const EventList& evt) const; + const std::string name() const; + template TH1D* operator()(const EventList& evt, const ARGS... args) const { return projInternal(evt, ArgumentPack(args...) ); } + + double operator()( const Event& evt ) const; + TH1D* plot(const std::string& prefix="") const; std::function binFunctor() const; @@ -40,6 +42,7 @@ namespace AmpGen friend class Projection2D; private: + TH1D* projInternal(const EventList&, const ArgumentPack&) const; std::function m_func; std::string m_name = {""}; std::string m_xAxisTitle = {""}; diff --git a/AmpGen/Vertex.h b/AmpGen/Vertex.h index ba62cb69cf6..d7856891272 100644 --- a/AmpGen/Vertex.h +++ b/AmpGen/Vertex.h @@ -159,6 +159,8 @@ namespace AmpGen DECLARE_VERTEX( S_ff_S1 ); DECLARE_VERTEX( V_ff_S ); DECLARE_VERTEX( V_ff_S1 ); + DECLARE_VERTEX( V_ff_PL ); + DECLARE_VERTEX( V_ff_PR ); class Factory : public AmpGen::Factory { public: diff --git a/Standalone.cmake b/Standalone.cmake index 1bf5289715a..bd4ddb1a84e 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -124,9 +124,7 @@ target_compile_options(AmpGen PUBLIC -Wall -Wextra -Wpedantic -g3 -Wno-unused-parameter - -Wno-unknown-pragmas - -Wnon-virtual-dtor - -Wno-overloaded-virtual + -Wdeprecated-copy -march=native $<$:-Ofast>) diff --git a/doc/release.notes b/doc/release.notes index c8b6404fe25..186a1246b62 100644 --- a/doc/release.notes +++ b/doc/release.notes @@ -7,6 +7,7 @@ - New phase space Generator TreePhaseSpace for producing narrow resonances. - Improved handling of CP conjugated amplitudes. - Add vertices f_fS_S{L,R} f_Vf_S{L,R} for couplings with well-defined chirality. + - Add initial states with ill-defined flavour to PolarisedSum !=================== AmpGen v1r2 2019-08-13 ================== - Tagged to match results in Gauss/LbAmpGen v49r14+ - Improved thread support for CoherentSum diff --git a/examples/FitterWithPolarisation.cpp b/examples/FitterWithPolarisation.cpp index 129970e3acd..05aa87beadc 100644 --- a/examples/FitterWithPolarisation.cpp +++ b/examples/FitterWithPolarisation.cpp @@ -98,8 +98,8 @@ int main( int argc, char* argv[] ) /* Generate events to normalise the PDF with. This can also be loaded from a file, which will be the case when efficiency variations are included. Default number of normalisation events - is 5 million. */ - EventList eventsMC = Generator<>(evtType, &rndm).generate(int(5e6)); + is 2 million. */ + EventList eventsMC = Generator<>(evtType, &rndm).generate(int(2e6)); sig.setMC( eventsMC ); diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp index 4ca7fec3cf6..8fbcf63695e 100644 --- a/examples/QcGenerator.cpp +++ b/examples/QcGenerator.cpp @@ -427,8 +427,9 @@ TTree* DTEventList::tree(const std::string& name) outputTree->Branch(("Tag_"+particleName(m_tagType, i)+"_ID").c_str(), &id_tag[i]); ids_tag[i] = ParticlePropertiesList::get( m_tagType[i] )->pdgID(); } + bool sym = NamedParameter("symmetrise",true); for( auto& evt: *this ){ - bool swap = gRandom->Uniform() > 0.5; + bool swap = sym && ( gRandom->Uniform() > 0.5 ); tmp.set(evt.signal, evt.tag); if( swap ) tmp.invertParity(); for(size_t i=0; i != m_sigType.size(); ++i) @@ -437,6 +438,7 @@ TTree* DTEventList::tree(const std::string& name) id_tag[i] = swap ? -ids_tag[i] : ids_tag[i]; outputTree->Fill(); } + return outputTree; } diff --git a/src/AddCPConjugate.cpp b/src/AddCPConjugate.cpp index 29252cc2c8f..fea88b44661 100644 --- a/src/AddCPConjugate.cpp +++ b/src/AddCPConjugate.cpp @@ -41,7 +41,9 @@ void AmpGen::AddCPConjugate( MinuitParameterSet& mps ) } } if( mps.find( new_name ) == nullptr ) + { tmp.push_back( new MinuitExpression(new_name, sgn * MinuitParameterLink(param) )) ; + } } for( auto& p : tmp ) mps.add( p ); } diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index cae67717ef8..79592f57307 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -201,6 +201,6 @@ bool TotalCoupling::isFixed() const bool TotalCoupling::contains( const std::string& label ) const { - return std::any_of(begin(), end(), [&label](auto& c){ return c.x()->name().find(label) != std::string::npos ; } ); + return std::any_of(begin(), end(), [&label](auto& c){ return c.name().find(label) != std::string::npos ; } ); } diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index f40b97ef6b0..5866ff52a0d 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -34,15 +34,15 @@ using namespace AmpGen; CoherentSum::CoherentSum() = default; CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, const std::string& prefix ) - : m_protoAmplitudes( mps ) - , m_evtType( type ) - , m_printFreq(NamedParameter( "CoherentSum::PrintFrequency", 100) ) - , m_dbThis (NamedParameter( "CoherentSum::Debug" , false)) - , m_verbosity(NamedParameter( "CoherentSum::Verbosity" , 0) ) - , m_objCache (NamedParameter("CoherentSum::ObjectCache" ,"") ) - , m_prefix( prefix ) + : m_rules(mps) + , m_evtType (type) + , m_printFreq (NamedParameter( "CoherentSum::PrintFrequency", 100) ) + , m_dbThis (NamedParameter( "CoherentSum::Debug" , false)) + , m_verbosity (NamedParameter( "CoherentSum::Verbosity" , 0) ) + , m_objCache (NamedParameter("CoherentSum::ObjectCache" ,"") ) + , m_prefix (prefix) { - auto amplitudes = m_protoAmplitudes.getMatchingRules( m_evtType, prefix); + auto amplitudes = m_rules.getMatchingRules( m_evtType, prefix); if( amplitudes.size() == 0 ){ WARNING("The defined amplitudes don't seem to be able to be able to generate eventType: " << type); } @@ -141,7 +141,7 @@ std::vector CoherentSum::fitFractions(const LinearErrorPropagator& prepare(); bool recomputeIntegrals = NamedParameter("CoherentSum::RecomputeIntegrals", false ); std::vector outputFractions; - for(auto& rule : m_protoAmplitudes.rules()) + for(auto& rule : m_rules.rules()) { FitFractionCalculator pCalc(this, findIndices(m_matrixElements, rule.first), recomputeIntegrals); for(auto& process : rule.second) @@ -155,7 +155,7 @@ std::vector CoherentSum::fitFractions(const LinearErrorPropagator& auto fractions = pCalc(rule.first, linProp); std::transform( fractions.begin(), fractions.end(), std::back_inserter(outputFractions),[](auto& p){ return p;} ); }; - auto ffForHead = m_protoAmplitudes.rulesForDecay(m_evtType.mother(), m_prefix); + auto ffForHead = m_rules.rulesForDecay(m_evtType.mother(), m_prefix); FitFractionCalculator iCalc(this, findIndices(m_matrixElements, m_evtType.mother()), recomputeIntegrals); for ( size_t i = 0; i < ffForHead.size(); ++i ) { diff --git a/src/EventList.cpp b/src/EventList.cpp index 5b6c01310ac..5068ba0d1b4 100644 --- a/src/EventList.cpp +++ b/src/EventList.cpp @@ -57,6 +57,11 @@ void EventList::loadFromFile( const std::string& fname, const ArgumentPack& args void EventList::loadFromTree( TTree* tree, const ArgumentPack& args ) { ProfileClock read_time; + if( m_eventType.size() == 0 ){ + auto tokens = split( tree->GetTitle(), ' '); + if( tokens.size() != 1 ) m_eventType = EventType( tokens ); + INFO("Attempted automatic deduction of eventType: " << m_eventType ); + } auto pdfSize = args.getArg(0).val; auto filter = args.getArg(std::string("")).val; auto getGenPdf = args.getArg(false).val; @@ -115,7 +120,9 @@ void EventList::loadFromTree( TTree* tree, const ArgumentPack& args ) TTree* EventList::tree( const std::string& name, const std::vector& extraBranches ) { - TTree* outputTree = new TTree( name.c_str(), name.c_str() ); + std::string title = m_eventType.mother(); + for( unsigned i = 0 ; i != m_eventType.size(); ++i ) title += " " + m_eventType[i]; + TTree* outputTree = new TTree( name.c_str(), title.c_str() ); if ( size() == 0 ) { ERROR( "Trying to output empty tree" ); return nullptr; diff --git a/src/EventType.cpp b/src/EventType.cpp index ffbabe1b3bd..ceff945be56 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -31,7 +31,8 @@ EventType::EventType( const std::vector& particleNames, const bool& throw std::runtime_error( "Not enough particles listed in particle names! Was it defined?" ); } m_mother = particleNames.at(0); - for ( unsigned int i = 1; i < particleNames.size(); ++i ) m_particleNames.push_back( particleNames[i] ); + m_alt_part_names = NamedParameter("EventType::AlternativeParticleNames", false ); + auto motherProperties = ParticlePropertiesList::get( m_mother ); if ( motherProperties != nullptr ) m_motherMass = motherProperties->mass(); @@ -39,19 +40,27 @@ EventType::EventType( const std::vector& particleNames, const bool& ERROR( "Particle not found: " << m_mother ); return; } - m_alt_part_names = NamedParameter("EventType::AlternativeParticleNames", false ); - for ( auto& particle : m_particleNames ) { - auto prop = ParticlePropertiesList::get( particle ); + + m_ignore.resize(particleNames.size()-1,false); + for ( auto it = particleNames.begin()+1; it != particleNames.end(); ++it ) + { + if( *it->begin() == '{' && *it->rbegin() == '}' ) + { + m_particleNames.push_back( it->substr(1, it->size() -2 ) ); + } + else m_particleNames.push_back( *it ); + + auto prop = ParticlePropertiesList::get( *m_particleNames.rbegin() ); if ( prop != nullptr ) m_particleMasses.push_back( prop->mass() ); else { - ERROR( "Particle not found: " << particle ); + ERROR( "Particle not found: " << *m_particleNames.rbegin() ); return; } if(m_alt_part_names) - m_particleNamesPickled.push_back( replaceAll( particle, {{"+","p"},{"-","m"},{"(",""},{")",""}})); + m_particleNamesPickled.push_back( replaceAll( *m_particleNames.rbegin(), {{"+","p"},{"-","m"},{"(",""},{")",""}})); else - m_particleNamesPickled.push_back( replaceAll( particle, {{"+","~"},{"-","#"},{"(",""},{")",""}})); + m_particleNamesPickled.push_back( replaceAll( *m_particleNames.rbegin(), {{"+","~"},{"-","#"},{"(",""},{")",""}})); } DEBUG( m_mother << " = " << m_motherMass << " -> " ); for ( unsigned int i = 0; i < m_particleNames.size(); ++i ) { diff --git a/src/Minimiser.cpp b/src/Minimiser.cpp index b5b3cefd3d2..5589c1fb2d0 100644 --- a/src/Minimiser.cpp +++ b/src/Minimiser.cpp @@ -106,6 +106,7 @@ bool Minimiser::doFit() } } m_status = m_minimiser->Status(); + /* for( unsigned i = 0 ; i != m_nParams; ++i ){ double low = 0; double high = 0; @@ -119,6 +120,7 @@ bool Minimiser::doFit() auto param = m_parSet->at( m_mapping[i] ); INFO( param->name() << " " << param->mean() << " " << param->errPos() << " " << param->errNeg() ); } + */ return 1; } diff --git a/src/Particle.cpp b/src/Particle.cpp index fd7fc00fbc2..e6b12032b3d 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -30,43 +30,40 @@ using namespace AmpGen; using namespace std::complex_literals; -Particle::Particle() - : m_spinFormalism { NamedParameter("Particle::SpinFormalism" ,"Covariant", "Spin formalism to use, can choose between Covariant and Canonical formalisms") } - , m_spinBasis { NamedParameter("Particle::SpinBasis" ,"Dirac", - optionalHelpString("Basis to use for calculating external polarisation tensors / spinors.", { - {"Dirac", "Quantises along the z-axis"} - , {"Weyl" , "Quantises along the direction of motion"}} ) )} - , m_defaultModifier { NamedParameter("Particle::DefaultModifier","", "Default modifier to use for lineshapes, for example to use normalised vs unnormalised Blatt-Weisskopf factors.") } - , m_cpOrderConvention {NamedParameter("Particle::CPOrderingConvention",true, "Making ordering of particles robust to CP conjugation")} -{} - -Particle::Particle( const std::string& name, const Particle& p1, const Particle& p2 ) - : Particle() -{ - m_props = ParticlePropertiesList::get( name ); - m_name = name; - m_daughters = { std::make_shared(p1), std::make_shared(p2) }; +Particle::Particle() = default; + +Particle::Particle( const std::string& name, const Particle& p1, const Particle& p2 ) : + m_name{name} + , m_props{ParticlePropertiesList::get(name)} + , m_daughters{ std::make_shared(p1), std::make_shared(p2) } +{ pdgLookup(); sortDaughters(); - for ( auto& d : m_daughters ) d->setTop( false ); + for ( auto& d : m_daughters ) d->setParent( this ); m_uniqueString = makeUniqueString(); } -Particle::Particle( const int& pdgID, const Particle& p1, const Particle& p2 ) - : Particle() -{ - m_props = ParticlePropertiesList::get( pdgID ); - m_daughters = {std::make_shared( p1 ) , std::make_shared( p2 ) }; +Particle::Particle( const int& pdgID, const Particle& p1, const Particle& p2 ) : + m_props{ParticlePropertiesList::get(pdgID)} + , m_daughters{std::make_shared(p1) , std::make_shared(p2) } +{ if ( m_props != nullptr ) m_name = m_props->name(); pdgLookup(); sortDaughters(); - for ( auto& d : m_daughters ) d->setTop( false ); + for ( auto& d : m_daughters ) d->setParent( this ); + m_uniqueString = makeUniqueString(); +} + +Particle::Particle( const std::string& name, const unsigned int& index ) : + m_props{ParticlePropertiesList::get( name )} + , m_index{index} +{ + pdgLookup(); m_uniqueString = makeUniqueString(); } Particle::Particle( const std::string& decayString, const std::vector& finalStates, const bool& orderDaughters ) - : Particle() { auto items = getItems( decayString ); if ( items.size() == 0 ) { @@ -78,7 +75,10 @@ Particle::Particle( const std::string& decayString, const std::vector( items[it] ) ); + for( size_t it = 1; it < items.size(); ++it ){ + m_daughters.push_back( std::make_shared( items[it] ) ); + (*m_daughters.rbegin())->setParent(this); + } m_props = ParticlePropertiesList::get( m_name ); pdgLookup(); auto fs = getFinalStateParticles( false ); @@ -104,14 +104,6 @@ Particle::Particle( const std::string& decayString, const std::vectorsetTop( false ); - m_uniqueString = makeUniqueString(); -} bool Particle::isValidDecayDescriptor( const std::string& decayDescriptor ) { @@ -165,14 +157,14 @@ void Particle::pdgLookup() } if ( m_lineshape == "BW" || m_usesDefaultLineshape ) { if ( m_name.find("NonRes") != std::string::npos || m_props->width() < ParticlePropertiesList::getMe()->quasiStableThreshold() ) m_lineshape = "FormFactor"; - if ( m_name == "gamma0" ) m_lineshape = "Photon"; + if ( m_props->isPhoton() ) m_lineshape = "Photon"; m_usesDefaultLineshape = true; } else m_usesDefaultLineshape = false; m_parity = m_props->P(); if ( !isdigit( m_props->J()[0] ) ) ERROR( "Spin not recognised! : " << m_name << " J = " << m_props->J() ); if( m_defaultModifier != "" && m_lineshape.find(".") == std::string::npos ){ - m_lineshape = m_lineshape + "." + m_defaultModifier; + m_lineshape = m_lineshape + "." + m_defaultModifier.getVal(); } bool isStrong = quarks() == daughterQuarks(); DEBUG( m_name << " is decaying via " << ( isStrong ? "strong" : "electroweak" ) << " interactions; P = " << props()->P() ); @@ -186,7 +178,7 @@ void Particle::pdgLookup() if ( m_orbital == 0 ) m_orbital = m_minL; // define in ground state unless specified int charge = 0; for ( auto& d : m_daughters ){ - d->setTop( false ); + d->setParent(this); charge += d->props()->charge(); } if( m_minL == 999 ) ERROR("Decay: " << m_name << " does not appear to have an allowed spin-orbit configuration"); @@ -384,13 +376,6 @@ Expression Particle::getExpression( DebugSymbols* db, const unsigned int& index { if( db != nullptr && !isStable() ) db->emplace_back( uniqueString() , Parameter( "NULL", 0, true ) ); - auto spinFormalism = m_spinFormalism; - auto localFormalism = attribute("SpinFormalism"); - if( localFormalism != stdx::nullopt ) localFormalism = localFormalism.value(); - if( spinFormalism != "Covariant" && spinFormalism != "Canonical") - { - FATAL("Invalid value for SpinFormalism: " << spinFormalism << ", possible values are: " << italic_on << " Covariant, Canonical." << italic_off ); - } Expression total = 0; Tensor::Index a; auto finalStateParticles = getFinalStateParticles(); @@ -401,11 +386,11 @@ Expression Particle::getExpression( DebugSymbols* db, const unsigned int& index std::vector exchangeParities; std::transform( finalStateParticles.begin(), finalStateParticles.end(), std::back_inserter(exchangeParities), [](const auto& p){ return p->props()->isFermion() ? -1 : 1; } ); - for(auto& ordering : orderings){ + for(const auto& ordering : orderings){ auto exchangeParity = minSwaps( ordering, exchangeParities ); setOrdering( ordering ); Expression spinFactor = 1; - if( includeSpin && spinFormalism == "Covariant" ){ + if( includeSpin && m_spinFormalism == spinFormalism::Covariant ){ Tensor st = spinTensor(db); if( m_props->twoSpin() == 0 ) spinFactor = st[0]; if( m_props->twoSpin() == 1 ){ @@ -416,7 +401,7 @@ Expression Particle::getExpression( DebugSymbols* db, const unsigned int& index ERROR("Spin tensor is the wrong rank = " << st.dimString() ); spinFactor = 1; } - else { spinFactor = is(a) * st(a) ; } + else spinFactor = is(a) * st(a) ; } if( m_props->twoSpin() == 2 ){ Tensor is = externalSpinTensor(m_polState).conjugate(); @@ -424,7 +409,7 @@ Expression Particle::getExpression( DebugSymbols* db, const unsigned int& index spinFactor = dot(is,st); } } - if ( includeSpin && spinFormalism == "Canonical" ){ + if ( includeSpin && m_spinFormalism == spinFormalism::Canonical ){ TransformSequence t = TransformSequence(); spinFactor = helicityAmplitude(*this, t, m_props->isBoson() ? polState() : double(polState())/2.0, db); } @@ -486,6 +471,11 @@ Tensor Particle::externalSpinTensor(const int& polState, DebugSymbols* db ) cons DEBUG("Getting final state spin tensor for: " << name() << " " << spin() ); if ( spin() == 0 ) return Tensor( std::vector( {1.} ), std::vector( {1} ) ); + if( m_spinBasis == spinBasis::Dirac && ( m_props->isPhoton() || m_props->isNeutrino() ) ) + { + WARNING("Use the Weyl (helicity) basis for calculations involving photons / neutrinos, as they don't have a rest frame. This will result in ill-defined amplitudes."); + } + Tensor p = P(); Expression pX = p.get(0); Expression pY = p.get(1); @@ -496,47 +486,52 @@ Tensor Particle::externalSpinTensor(const int& polState, DebugSymbols* db ) cons Expression z = pX + 1i*pY; Expression zb = pX - 1i*pY; auto id = props()->pdgID(); - if ( m_props->twoSpin() == 2 && m_spinBasis == "Weyl" ) { - Expression N = 1./(sqrt(2)); - Expression invPT2 = make_cse(Ternary( pX*pX + pY*pY > 1e-6, 1./(pX*pX+pY*pY), 0 )); - Expression invP = make_cse(Ternary( pP > 1e-6, 1./pP,0)); - Expression pZoverP = make_cse(Ternary( pP > 1e-6, pZ/pP, 1) ); - Expression f = (pP-pZ)*invPT2; - if(polState == 1) return N * Tensor({-pZoverP + 1i*z *pY*f*invP, -1i*pZoverP - 1i*z *pX*f*invP, z*invP , 0. }); - if(polState == -1) return N * Tensor({ pZoverP + 1i*zb*pY*f*invP, -1i*pZoverP - 1i*zb*pX*f*invP,-zb*invP , 0. }); - if(polState == 0) return Tensor({pX*pE*invP/m , pY*pE*invP/m , pZoverP*pE/m, pP/m}); - } - if( m_props->twoSpin() == 2 && m_spinBasis == "Dirac" ){ - if( name() == "gamma0" ){ - ERROR("Use the Weyl (helicity) basis for calculations involving photons, as they don't have a rest frame. This will result in ill-defined amplitudes."); + if ( m_props->twoSpin() == 2 ) + { + if( m_spinBasis == spinBasis::Weyl ) + { + Expression N = 1./(sqrt(2)); + Expression invPT2 = make_cse(Ternary( pX*pX + pY*pY > 1e-6, 1./(pX*pX+pY*pY), 0 )); + Expression invP = make_cse(Ternary( pP > 1e-6, 1./pP,0)); + Expression pZoverP = make_cse(Ternary( pP > 1e-6, pZ/pP, 1) ); + Expression f = (pP-pZ)*invPT2; + if(polState == 1) return N * Tensor({-pZoverP + 1i*z *pY*f*invP, -1i*pZoverP - 1i*z *pX*f*invP, z*invP , 0. }); + if(polState == -1) return N * Tensor({ pZoverP + 1i*zb*pY*f*invP, -1i*pZoverP - 1i*zb*pX*f*invP,-zb*invP , 0. }); + if(polState == 0) return Tensor({pX*pE*invP/m , pY*pE*invP/m , pZoverP*pE/m, pP/m}); + } + if( m_spinBasis == spinBasis::Dirac ){ + Expression N = make_cse(1./(m*(pE + m))); + if( polState == 1 ) return -Tensor({1.+ z *pX*N, 1i + z*pY*N, z*pZ*N , z*m })/sqrt(2); + if( polState == -1 ) return Tensor({1.+ zb*pX*N, -1i + zb*pY*N, zb*pZ*N , zb*m })/sqrt(2); + if( polState == 0 ) return Tensor({pX*pZ*N , pY*pZ*N, 1 + pZ*pZ*N, pZ/m }); } - Expression N = make_cse(1./(m*(pE + m))); - if( polState == 1 ) return -Tensor({1.+ z *pX*N, 1i + z*pY*N, z*pZ*N , z*m })/sqrt(2); - if( polState == -1 ) return Tensor({1.+ zb*pX*N, -1i + zb*pY*N, zb*pZ*N , zb*m })/sqrt(2); - if( polState == 0 ) return Tensor({pX*pZ*N , pY*pZ*N, 1 + pZ*pZ*N, pZ/m }); - } - if( m_props->twoSpin() == 1 && m_spinBasis == "Weyl" ){ - Expression n = fcn::sqrt( 2 * pP*(pP+pZ) ); - double isqrt_two = 1./sqrt(2); - Expression fa = fcn::sqrt(pE/m + 1); - Expression fb = fcn::sqrt(pE/m - 1); - Expression aligned = make_cse( Abs(pP + pZ) < 10e-6 ) ; - Expression xi10 = make_cse(Ternary( aligned, 1, (pP+pZ)/n )); - Expression xi11 = make_cse(Ternary( aligned, 0, z/n )); - Expression xi00 = make_cse(Ternary( aligned, 0, -zb/n )); - Expression xi01 = make_cse(Ternary( aligned, 1, (pP+pZ)/n )); - if(id > 0 && polState == 1) return isqrt_two * Tensor({ fa*xi10, fa*xi11, fb*xi10, fb*xi11 } ); - if(id > 0 && polState == -1) return isqrt_two * Tensor({ fa*xi00, fa*xi01, -fb*xi00, -fb*xi01 } ); - if(id < 0 && polState == 1) return isqrt_two * Tensor({ fb*xi00, fb*xi01, -fa*xi00, -fa*xi01 } ); - if(id < 0 && polState == -1) return isqrt_two * Tensor({ fb*xi10, fb*xi11, -fa*xi01, -fa*xi11 } ); - } - if ( m_props->twoSpin() == 1 && m_spinBasis == "Dirac" ) + } + if( m_props->twoSpin() == 1 ) { - Expression norm = make_cse( fcn::sqrt((pE+m)/(2*m) )); - if(id > 0 && polState == 1 ) return norm * Tensor({ 1 ,0 , pZ/(pE+m), z/(pE+m) }); - if(id > 0 && polState == -1 ) return norm * Tensor({ 0 ,1 , zb/(pE+m), -pZ/(pE+m) }); - if(id < 0 && polState == -1 ) return norm * Tensor({ pZ/(pE+m), z/(pE+m) , 1 ,0 }); - if(id < 0 && polState == 1 ) return norm * Tensor({ zb/(pE+m),-pZ/(pE+m) , 0 ,1 }); + if( m_spinBasis == spinBasis::Weyl ) + { + Expression n = fcn::sqrt( 2 * pP*(pP+pZ) ); + double isqrt_two = 1./sqrt(2); + Expression fa = m_props->isNeutrino() ? 2 : fcn::sqrt(pE/m + 1); + Expression fb = m_props->isNeutrino() ? 0 : fcn::sqrt(pE/m - 1); + Expression aligned = make_cse( Abs(pP + pZ) < 10e-6 ) ; + Expression xi10 = make_cse(Ternary( aligned, 1, (pP+pZ)/n )); + Expression xi11 = make_cse(Ternary( aligned, 0, z/n )); + Expression xi00 = make_cse(Ternary( aligned, 0, -zb/n )); + Expression xi01 = make_cse(Ternary( aligned, 1, (pP+pZ)/n )); + if(id > 0 && polState == 1) return isqrt_two * Tensor({ fa*xi10, fa*xi11, fb*xi10, fb*xi11 } ); + if(id > 0 && polState == -1) return isqrt_two * Tensor({ fa*xi00, fa*xi01, -fb*xi00, -fb*xi01 } ); + if(id < 0 && polState == 1) return isqrt_two * Tensor({ fb*xi00, fb*xi01, -fa*xi00, -fa*xi01 } ); + if(id < 0 && polState == -1) return isqrt_two * Tensor({ fb*xi10, fb*xi11, -fa*xi01, -fa*xi11 } ); + } + if ( m_spinBasis == spinBasis::Dirac ) + { + Expression N = make_cse( fcn::sqrt((pE+m)/(2*m) )); + if(id > 0 && polState == 1 ) return N * Tensor({ 1 ,0 , pZ/(pE+m), z/(pE+m) }); + if(id > 0 && polState == -1 ) return N * Tensor({ 0 ,1 , zb/(pE+m), -pZ/(pE+m) }); + if(id < 0 && polState == -1 ) return N * Tensor({ pZ/(pE+m), z/(pE+m) , 1 ,0 }); + if(id < 0 && polState == 1 ) return N * Tensor({ zb/(pE+m),-pZ/(pE+m) , 0 ,1 }); + } } std::string js = m_props->isBoson() ? std::to_string(m_props->twoSpin()/2) : std::to_string(m_props->twoSpin()) +"/2"; WARNING("Spin tensors not implemented for spin J = " << js << "; m = " << m_polState << " " << m_name ); @@ -598,13 +593,13 @@ std::string Particle::texLabel( const bool& printHead, const bool& recurse ) con const std::string rightBrace = "\\right]"; if( m_daughters.size() == 0 ) return m_props->label(); std::string val = ""; // m_props->label(); - if( !m_isHead ) val = m_props->label(); - if( printHead && m_isHead ) val = m_props->label() + "\\rightarrow "; + if( !isHead() ) val = m_props->label(); + if( printHead && isHead() ) val = m_props->label() + "\\rightarrow "; - if( m_isHead || recurse ){ - if ( !m_isHead || m_orbital != m_minL ) val += leftBrace; + if( isHead() || recurse ){ + if ( !isHead() || m_orbital != m_minL ) val += leftBrace; for( auto& prod : m_daughters ) val += prod->texLabel(false,recurse) + " "; - if ( !m_isHead || m_orbital != m_minL ) val += rightBrace; + if ( !isHead() || m_orbital != m_minL ) val += rightBrace; if ( m_orbital != m_minL ) val += "^{" + orbitalString() + "}"; } return val; @@ -613,9 +608,9 @@ std::string Particle::texLabel( const bool& printHead, const bool& recurse ) con void Particle::sortDaughters() { bool isAntiParticle = m_props->pdgID() < 0; - if( m_cpOrderConvention && isAntiParticle ) conjThis(); + if( isAntiParticle ) conjThis(); std::stable_sort( m_daughters.begin(), m_daughters.end(), [](const auto& A, const auto& B) { return *A < *B; } ); - if( m_cpOrderConvention && isAntiParticle ) conjThis(); + if( isAntiParticle ) conjThis(); m_uniqueString = makeUniqueString(); } @@ -630,7 +625,7 @@ Particle Particle::conj( bool invertHead , bool reorder ) { Particle cp(*this); cp.clearDecayProducts(); - const ParticleProperties* p = ( !m_isHead || invertHead ) && m_props->hasDistinctAnti() ? ParticlePropertiesList::get( -m_props->pdgID() ) : m_props; + const ParticleProperties* p = ( !isHead() || invertHead ) && m_props->hasDistinctAnti() ? ParticlePropertiesList::get( -m_props->pdgID() ) : m_props; cp.setName( p->name() ); for( auto& d : m_daughters ) cp.addDaughter( std::make_shared(d->conj(invertHead,reorder)) ); if( reorder ) cp.sortDaughters(); @@ -669,7 +664,6 @@ void Particle::setName(const std::string& name) m_props = ParticlePropertiesList::get(name); m_parity = m_props->P(); } -void Particle::setTop( bool state ) { m_isHead = state; } void Particle::setIndex( const unsigned int& index, const bool& setOri ) { m_index = index; @@ -712,7 +706,7 @@ std::string Particle::topologicalString() const } const ParticleProperties* Particle::props() const { return m_props; } -bool Particle::isHead() const { return m_isHead; } +bool Particle::isHead() const { return m_parent == nullptr; } bool Particle::isWeakDecay() const { return quarks() == daughterQuarks(); } bool Particle::isStateGood() const { return m_isStateGood; } bool Particle::isStable() const { return m_daughters.size() == 0; } @@ -737,6 +731,11 @@ void Particle::setDaughter( const Particle& particle, const unsigned int& index makeUniqueString(); } +void Particle::setParent(const Particle* ptr ) +{ + m_parent = ptr; +} + std::vector> Particle::daughters() const { return m_daughters; } bool Particle::operator<( const Particle& other ) @@ -781,6 +780,14 @@ void Particle::setPolarisationState( const int& state ) m_uniqueString = makeUniqueString(); } +void Particle::setPolarisationState( const std::vector& state ) +{ + setPolarisationState( state[0] ); + auto fs = getFinalStateParticles(); + for(size_t i = 0 ; i < fs.size(); ++i ) fs[i]->setPolarisationState( state[i+1] ); + m_uniqueString = makeUniqueString(); +} + unsigned int Particle::matches( const Particle& other ) const { unsigned int rt=0; @@ -829,3 +836,9 @@ stdx::optional Particle::attribute(const std::string& key) const std::ostream& AmpGen::operator<<( std::ostream& os, const Particle& particle ){ return os << particle.decayDescriptor(); } + +namespace AmpGen { + complete_enum( spinFormalism, Covariant, Canonical ) + complete_enum( spinBasis , Dirac , Weyl ) +} + diff --git a/src/ParticleProperties.cpp b/src/ParticleProperties.cpp index 77d55d03b7e..e9e512fe95e 100644 --- a/src/ParticleProperties.cpp +++ b/src/ParticleProperties.cpp @@ -143,6 +143,16 @@ bool ParticleProperties::isFermion() const { return m_twoSpin % 2 == 1; } +bool ParticleProperties::isPhoton() const +{ + return m_name == "gamma0"; +} + +bool ParticleProperties::isNeutrino() const +{ + return abs(m_pdgID) == 12 || abs(m_pdgID) == 14 || abs(m_pdgID) == 16; +} + bool ParticleProperties::isBoson() const { return ! isFermion(); } diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 1b2cbe12c8f..be530d1a360 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -28,63 +28,91 @@ #include "AmpGen/ProfileClock.h" #include "AmpGen/DiracMatrices.h" #include "AmpGen/Simplify.h" +#include "AmpGen/enum.h" using namespace AmpGen; using namespace std::complex_literals; +namespace AmpGen { + make_enum(spaceType, spin, flavour) +} + PolarisedSum::PolarisedSum( const EventType& type, MinuitParameterSet& mps, - const std::string& prefix ) : - m_mps(&mps), - m_eventType(type), - m_prefix(prefix) + const std::string& prefix ) + : m_mps (&mps) + , m_verbosity (NamedParameter("PolarisedSum::Verbosity", 0 )) + , m_debug (NamedParameter("PolarisedSum::Debug" , false )) + , m_eventType (type) + , m_prefix (prefix) + , m_rules (mps) + , m_dim (m_eventType.dim()) { - m_debug = NamedParameter( "PolarisedSum::Debug" ,false ); std::string objCache = NamedParameter("PolarisedSum::ObjectCache","" ); - m_verbosity = NamedParameter( "PolarisedSum::Verbosity" ,0 ); - m_rules = AmplitudeRules(mps); - auto protoAmps = m_rules.getMatchingRules( type, prefix); - auto prodPols = polarisations( type.mother() ); - for(auto& pol : prodPols ) m_polStates.push_back({pol}); - for(size_t i = 0 ; i < type.size(); ++i ) m_polStates = polarisationOuterProduct(m_polStates, polarisations( type[i] ) ); - auto set_polarisation_state = []( auto& matrix_element, auto& polState ){ - auto fs = matrix_element.first.getFinalStateParticles(); - matrix_element.first.setPolarisationState(polState[0]); - for(size_t i = 0 ; i < fs.size(); ++i ) fs[i]->setPolarisationState( polState[i+1] ); - }; - for( auto& m : protoAmps ) INFO( m.first.uniqueString() ); - m_matrixElements.resize( protoAmps.size() ); - - ThreadPool tp(8); - for(unsigned i = 0; i < m_matrixElements.size(); ++i) + spaceType stype = NamedParameter("PolarisedSum::SpaceType", spaceType::spin); + if( stype == spaceType::spin ) { - tp.enqueue( [i,this,&mps,&protoAmps, &set_polarisation_state]{ - Tensor thisExpression( Tensor::dim(this->m_polStates.size()) ); - DebugSymbols syms; - for( unsigned j=0;j> polStates; + for(const auto& pol : prodPols ) polStates.push_back({pol}); + for(unsigned i = 0 ; i != type.size(); ++i ) polStates = indexProduct(polStates, polarisations( type[i] ) ); + + auto protoAmps = m_rules.getMatchingRules(m_eventType, m_prefix); + for(const auto& m : protoAmps ) INFO( m.first.uniqueString() ); + m_matrixElements.resize( protoAmps.size() ); + ThreadPool tp(8); + for(unsigned i = 0; i < m_matrixElements.size(); ++i) + { + tp.enqueue( [i, &protoAmps, &polStates, this]{ + Tensor thisExpression( Tensor::dim(polStates.size()) ); + auto& [p,coupling] = protoAmps.at(i); + DebugSymbols syms; + for(unsigned j = 0; j != polStates.size(); ++j){ + p.setPolarisationState( polStates[j] ); + thisExpression[j] = make_cse( p.getExpression(&syms) ); + } + m_matrixElements[i] = TransitionMatrix>( + p, + coupling, + CompiledExpression< std::vector,const real_t*, const real_t*>( + TensorExpression(thisExpression), + p.decayDescriptor(), + this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,this->m_mps ) ); + CompilerWrapper().compile( m_matrixElements[i].amp ); + }); } - m_matrixElements[i] = TransitionMatrix>( - protoAmps[i].first, - protoAmps[i].second, - CompiledExpression< std::vector,const real_t*, const real_t*>( - TensorExpression(thisExpression), - protoAmps[i].first.decayDescriptor(), - this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,&mps ) ); - CompilerWrapper().compile( m_matrixElements[i].amp ); - }); - } - - auto d = m_eventType.dim(); - auto p = [&mps](const std::string& name){ return mps.addOrGet(name, Flag::Fix, 0, 0); }; - if( d.first == 1 ) m_pVector = {}; - else if( d.first == 2 ) m_pVector = {p("Px"), p("Py"), p("Pz")}; - else if( d.first == 3 ) m_pVector = {p("Px"), p("Py"), p("Pz"), p("Tyy"), p("Tzz"), p("Txy"), p("Txz"), p("Tyz")}; - size_t normSize = d.second * d.first * d.first; - for(size_t i=0; i < normSize; ++i){ - m_norms.emplace_back( m_matrixElements.size(), m_matrixElements.size() ); - } + } + if ( stype == spaceType::flavour ) + { + m_dim = {2,1}; + auto r1 = m_rules.getMatchingRules(m_eventType, m_prefix); + auto r2 = m_rules.getMatchingRules(m_eventType.conj(true), m_prefix); + m_matrixElements.resize( r1.size() + r2.size() ); + ThreadPool tp(8); + for(unsigned i = 0 ; i != m_matrixElements.size(); ++i) + { + tp.enqueue( [i, this, &r1, &r2]{ + Tensor thisExpression( Tensor::dim(2) ); + DebugSymbols syms; + auto& tm = i < r1.size() ? r1[i] : r2[i-r1.size()]; + thisExpression[0] = i < r1.size() ? make_cse( tm.first.getExpression(&syms) ) : 0; + thisExpression[1] = i < r1.size() ? 0 : make_cse( tm.first.getExpression(&syms) ); + m_matrixElements[i] = TransitionMatrix>( + tm.first, + tm.second, + CompiledExpression< std::vector,const real_t*, const real_t*>( + TensorExpression(thisExpression), + tm.first.decayDescriptor(), + this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,this->m_mps ) ); + CompilerWrapper().compile( m_matrixElements[i].amp ); + }); + } + } + auto p = [this](const std::string& name){ return this->m_mps->addOrGet(name, Flag::Fix, 0, 0); }; + if( m_dim.first == 1 ) m_pVector = {}; + else if( m_dim.first == 2 ) m_pVector = {p("Px"), p("Py"), p("Pz")}; + else if( m_dim.first == 3 ) m_pVector = {p("Px"), p("Py"), p("Pz"), p("Tyy"), p("Tzz"), p("Txy"), p("Txz"), p("Tyz")}; + for(size_t i=0; i < m_dim.second * m_dim.first * m_dim.first; ++i) m_norms.emplace_back( m_matrixElements.size(), m_matrixElements.size() ); } std::vector PolarisedSum::polarisations( const std::string& name ) const @@ -102,7 +130,7 @@ std::vector PolarisedSum::polarisations( const std::string& name ) const } } -std::vector> PolarisedSum::polarisationOuterProduct(const std::vector>& A, const std::vector& B ) const +std::vector> PolarisedSum::indexProduct(const std::vector>& A, const std::vector& B ) const { std::vector> rt; for( auto& iA : A ){ @@ -114,21 +142,18 @@ std::vector> PolarisedSum::polarisationOuterProduct(const std:: return rt; } -std::vector densityMatrix(const size_t& dim, const std::vector& pv ) +std::vector densityMatrix(const unsigned& dim, const std::vector& pv ) { - INFO( "Dim = " << dim << ", " << pv.size() ); - if( dim != 2 || dim != 3 ) + if( dim != 2 && dim != 3 ) { std::vector rt(dim*dim); for( unsigned i = 0 ; i != dim; ++i ) rt[ dim*i +i ] = 1; return rt; } - - if( dim == 1 ) return {1.}; double px = pv[0]; double py = pv[1]; double pz = pv[2]; - if( dim == 2 ) return {1+pz , px+1i*py, + if( dim == 2 ) return {1+pz , px+1i*py, px-1i*py, 1-pz }; if( dim == 3 ){ double Tyy = pv[3]; @@ -160,7 +185,6 @@ void PolarisedSum::prepare() { DEBUG( "Preparing: " << m_prefix << " " << m_events << " ready = " << m_integrator.isReady() ); transferParameters(); - auto dim = m_eventType.dim(); std::vector hasChanged( m_matrixElements.size(), false); size_t nChanges = 0; ProfileClock tEval; @@ -171,7 +195,7 @@ void PolarisedSum::prepare() ProfileClock tMEval; auto& t = m_matrixElements[i]; if( m_nCalls != 0 && !t.amp.hasExternalsChanged() ) continue; - if( t.addressData == 999 ) t.addressData = m_events->registerExpression(t.amp, dim.first * dim.second ); + if( t.addressData == 999 ) t.addressData = m_events->registerExpression(t.amp, m_dim.first * m_dim.second ); m_events->updateCache(t.amp, t.addressData); m_integrator.prepareExpression(t.amp, size_of); tMEval.stop(); @@ -184,7 +208,7 @@ void PolarisedSum::prepare() m_weight = m_weightParam == nullptr ? 1 : m_weightParam->mean(); tEval.stop(); ProfileClock tIntegral; - m_rho = densityMatrix(m_eventType.dim().first, m_pVector); + m_rho = densityMatrix(m_dim.first, m_pVector); if( m_integrator.isReady() ) { if(nChanges != 0) calculateNorms(hasChanged); @@ -231,8 +255,7 @@ void PolarisedSum::setMC( EventList& events ) size_t PolarisedSum::size() const { - auto dim = m_eventType.dim() ; - return dim.first * dim.second * m_matrixElements.size(); + return m_dim.first * m_dim.second * m_matrixElements.size(); } void PolarisedSum::reset( const bool& flag ){ m_nCalls = 0 ; } @@ -248,8 +271,7 @@ void PolarisedSum::build_probunnormalised() Tensor PolarisedSum::transitionMatrix() { - auto dim = m_eventType.dim(); - auto size = dim.first * dim.second ; + auto size = m_dim.first * m_dim.second; std::vector expressions(size, 0); for( auto& me : m_matrixElements ){ auto coupling = me.coupling.to_expression() ; @@ -258,7 +280,7 @@ Tensor PolarisedSum::transitionMatrix() expressions[i] = expressions[i] + coupling * Parameter( "x1["+std::to_string(cacheIndex+i)+"]",0,true); } } - Tensor T_matrix(expressions, {dim.first, dim.second}); + Tensor T_matrix(expressions, {m_dim.first, m_dim.second}); T_matrix.st(); return T_matrix; } @@ -278,9 +300,8 @@ complex_t PolarisedSum::norm(const size_t& i, const size_t& j, PolarisedSum::int auto ai = m_integIndex[i]; auto aj = m_integIndex[j]; complex_t total = 0; - auto dim = m_eventType.dim(); - auto s1 = dim.first; - auto s2 = dim.second; + auto s1 = m_dim.first; + auto s2 = m_dim.second; for(size_t x = 0 ; x < m_norms.size(); ++x){ auto f = x % s2; auto psiIndex = (x-f) / s2; @@ -293,8 +314,8 @@ complex_t PolarisedSum::norm(const size_t& i, const size_t& j, PolarisedSum::int void PolarisedSum::calculateNorms(const std::vector& hasChanged) { - for( size_t i = 0 ; i < m_matrixElements.size(); ++i ){ - for( size_t j = i; j < m_matrixElements.size(); ++j ){ + for( unsigned i = 0 ; i < m_matrixElements.size(); ++i ){ + for( unsigned j = i; j < m_matrixElements.size(); ++j ){ if( hasChanged[i] || hasChanged[j] ) norm(i, j, &m_integrator); } } @@ -308,12 +329,11 @@ double PolarisedSum::prob(const Event& evt) const void PolarisedSum::debug(const Event& evt) { - auto dim = m_eventType.dim(); - size_t tsize = dim.first * dim.second; - for(auto& me : m_matrixElements) + auto tsize = m_dim.first * m_dim.second; + for(const auto& me : m_matrixElements) { std::vector this_cache(0,tsize); - for(size_t i = 0 ; i < tsize; ++i ) this_cache.emplace_back( evt.getCache(me.addressData+i) ); + for(unsigned i = 0 ; i != tsize; ++i ) this_cache.emplace_back( evt.getCache(me.addressData+i) ); INFO( me.decayDescriptor() << " " << vectorToString( this_cache, " ") ); } INFO("P(x) = " << getValNoCache(evt) ); @@ -335,8 +355,7 @@ void PolarisedSum::generateSourceCode(const std::string& fname, const double& no { INFO("Generating sourceCode -> " << fname ); std::ofstream stream( fname ); - auto dim = m_eventType.dim(); - size_t size = dim.first * dim.second; + size_t size = m_dim.first * m_dim.second; CompilerWrapper().preamble( stream ); Expression event = Parameter("x0",0,true); std::vector expressions(size); @@ -350,7 +369,7 @@ void PolarisedSum::generateSourceCode(const std::string& fname, const double& no expressions[j] = expressions[j] + p.coupling() * z[j]; } } - Tensor T_matrix( expressions, {dim.first,dim.second} ); + Tensor T_matrix( expressions, {m_dim.first, m_dim.second} ); T_matrix.st(); auto amp = probExpression(T_matrix, convertProxies(m_pVector, [](auto& proxy) -> Expression{ return double(proxy);} )); auto amp_extPol = probExpression(T_matrix, {Parameter("x2",0,true), Parameter("x3",0,true), Parameter("x4",0,true)}); @@ -463,5 +482,5 @@ real_t PolarisedSum::getValNoCache( const Event& evt ) return m_probExpression( copy.getCachePtr() ); } -void PolarisedSum::setWeight( MinuitParameter* param ){ m_weightParam = param ; } +void PolarisedSum::setWeight( MinuitParameter* param ){ m_weightParam = param ; } double PolarisedSum::getWeight() const { return m_weightParam == nullptr ? 1.0 : m_weightParam->mean() ; } diff --git a/src/Projection.cpp b/src/Projection.cpp index f11ba7a1828..aacf9ea405b 100644 --- a/src/Projection.cpp +++ b/src/Projection.cpp @@ -70,4 +70,7 @@ std::pair Projection2D::operator()( const Event& evt ) const return {xAxis.m_func( evt ), yAxis.m_func( evt )}; } -TH1D* Projection::operator()( const EventList& events) const { return events.makeProjection(*this); } +TH1D* Projection::projInternal( const EventList& events, const ArgumentPack& args) const +{ + return events.makeProjection(*this, args); +} diff --git a/src/TreePhaseSpace.cpp b/src/TreePhaseSpace.cpp index a6f0f25bbb7..1f35c090575 100644 --- a/src/TreePhaseSpace.cpp +++ b/src/TreePhaseSpace.cpp @@ -59,27 +59,27 @@ Event TreePhaseSpace::makeEvent( const unsigned& cacheSize ) void TreePhaseSpace::provideEfficiencyReport(const std::vector& report) { - if( report.size() != m_generatorRecord.size() ) - { - WARNING("Report does not match size of generator record..."); - return; - } - std::vector counters( m_top.size() ); - std::vector totals ( m_top.size() ); - unsigned counter = 0; - for( unsigned i = 0 ; i != report.size(); ++i ) - { - counters[m_generatorRecord[i]] += report[i]; - totals[m_generatorRecord[i]] ++; - counter += report[i]; - } - for( unsigned i = 0 ; i != m_top.size(); ++i ) - { - INFO( m_top[i].particle.decayDescriptor() << " " << counters[i] << " / " << totals[i] ); - m_weights[i] = double( counters[i] ) / double( counter ); - } - m_dice = std::discrete_distribution<>(m_weights.begin(), m_weights.end()); - m_generatorRecord.clear(); +// if( report.size() != m_generatorRecord.size() ) +// { +// WARNING("Report does not match size of generator record..."); +// return; +// } +// std::vector counters( m_top.size() ); +// std::vector totals ( m_top.size() ); +// unsigned counter = 0; +// for( unsigned i = 0 ; i != report.size(); ++i ) +// { +// counters[m_generatorRecord[i]] += report[i]; +// totals[m_generatorRecord[i]] ++; +// counter += report[i]; +// } +// for( unsigned i = 0 ; i != m_top.size(); ++i ) +// { +// INFO( m_top[i].particle.decayDescriptor() << " " << counters[i] << " / " << totals[i] ); +// m_weights[i] = double( counters[i] ) / double( counter ); +// } +// m_dice = std::discrete_distribution<>(m_weights.begin(), m_weights.end()); +// m_generatorRecord.clear(); } double rho( const double& s, const double& s1, const double& s2) diff --git a/src/Vertex.cpp b/src/Vertex.cpp index 4af6ab7c40d..2a3029e7f21 100644 --- a/src/Vertex.cpp +++ b/src/Vertex.cpp @@ -422,3 +422,15 @@ DEFINE_VERTEX( S_ff_S1 ){ return Bar(V2)(a) * Gamma[4](a,b) * V1(b); } DEFINE_VERTEX( V_ff_S ) { return Bar(V2)(a) * Gamma4Vec()(mu,a,b) * V1(b); } DEFINE_VERTEX( V_ff_S1 ){ return Bar(V2)(a) * Gamma[4](a,b) * Gamma4Vec()(mu,b,c) * V1(c); } + +DEFINE_VERTEX( V_ff_PL ) +{ + Tensor proj = Spin1Projector(P); + return proj(mu, nu) * Bar(V1)(a) * Gamma4Vec()(-nu,a,b) * ( Identity(4) - Gamma[4] )(b,c)* V2(c); +} + +DEFINE_VERTEX( V_ff_PR ) +{ + Tensor proj = Spin1Projector(P); + return proj(mu, nu) * Bar(V1)(a) * Gamma4Vec()(-nu,a,b) * ( Identity(4) + Gamma[4] )(b,c)* V2(c); +} diff --git a/test/test_NamedParameter.cpp b/test/test_NamedParameter.cpp index 025d3b48e77..9d7798fc249 100644 --- a/test/test_NamedParameter.cpp +++ b/test/test_NamedParameter.cpp @@ -7,7 +7,7 @@ BOOST_AUTO_TEST_CASE ( constructors_right ) { - AmpGen::NamedParameter param("test_param", 4); - BOOST_CHECK( param == 4 ); + AmpGen::NamedParameter param("test_param", 4); + BOOST_CHECK( param == unsigned(4) ); } From 582726218170cb917e1255ec58956ed0bce8153f Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 9 Jan 2020 17:58:32 +0100 Subject: [PATCH 113/250] Remove compile flag for warnings of depreciated copy constructors --- Standalone.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/Standalone.cmake b/Standalone.cmake index bd4ddb1a84e..022bb4b1d2f 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -124,7 +124,6 @@ target_compile_options(AmpGen PUBLIC -Wall -Wextra -Wpedantic -g3 -Wno-unused-parameter - -Wdeprecated-copy -march=native $<$:-Ofast>) From ecfb7a414a93cdfd01a0adc3baa9117c1ca02967 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 9 Jan 2020 18:18:43 +0100 Subject: [PATCH 114/250] Change default cxx standard to 17 --- Standalone.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Standalone.cmake b/Standalone.cmake index 022bb4b1d2f..5956fc0ce64 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -4,7 +4,7 @@ file(GLOB_RECURSE AMPGEN_SRC src/*) file(GLOB_RECURSE AMPGEN_HDR AmpGen/*) if( NOT "${CMAKE_CXX_STANDARD}" ) - set(CMAKE_CXX_STANDARD 14) + set(CMAKE_CXX_STANDARD 17) endif() SET(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") From 871d59f4958e16a426228d2c3352c557715b94e6 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 9 Jan 2020 18:22:44 +0100 Subject: [PATCH 115/250] Add gcc8 to .travis.yml --- .travis.yml | 1 + Standalone.cmake | 1 + 2 files changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 02705555df0..e164e02bd62 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,6 +25,7 @@ env: addons: apt: packages: + - g++-8 - doxygen - doxygen-doc - doxygen-gui diff --git a/Standalone.cmake b/Standalone.cmake index 5956fc0ce64..4970d6af8f1 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -124,6 +124,7 @@ target_compile_options(AmpGen PUBLIC -Wall -Wextra -Wpedantic -g3 -Wno-unused-parameter + -Wno-unknown-pragmas -march=native $<$:-Ofast>) From 998e603abbd8f31d12b16992ba8b4dada840153e Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 9 Jan 2020 18:25:36 +0100 Subject: [PATCH 116/250] Add gcc8 to .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e164e02bd62..6b5a786ace1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,7 @@ env: addons: apt: packages: - - g++-8 + - gcc-8 - doxygen - doxygen-doc - doxygen-gui From 6618b99e8a59cb8c44868d99b1112b951037d682 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 9 Jan 2020 18:37:10 +0100 Subject: [PATCH 117/250] Downgrade cxx standard to make travis happy --- .travis.yml | 1 - Standalone.cmake | 2 +- src/PolarisedSum.cpp | 4 +++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6b5a786ace1..02705555df0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,6 @@ env: addons: apt: packages: - - gcc-8 - doxygen - doxygen-doc - doxygen-gui diff --git a/Standalone.cmake b/Standalone.cmake index 4970d6af8f1..8828b12f415 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -4,7 +4,7 @@ file(GLOB_RECURSE AMPGEN_SRC src/*) file(GLOB_RECURSE AMPGEN_HDR AmpGen/*) if( NOT "${CMAKE_CXX_STANDARD}" ) - set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD 14) endif() SET(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index be530d1a360..2e4a4ce75df 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -65,7 +65,9 @@ PolarisedSum::PolarisedSum( const EventType& type, { tp.enqueue( [i, &protoAmps, &polStates, this]{ Tensor thisExpression( Tensor::dim(polStates.size()) ); - auto& [p,coupling] = protoAmps.at(i); + auto& p = protoAmps[i].first; + auto& coupling = protoAmps[i].second; + //auto& [p,coupling] = protoAmps.at(i); DebugSymbols syms; for(unsigned j = 0; j != polStates.size(); ++j){ p.setPolarisationState( polStates[j] ); From b91e8a679cebcd342d03e4864b7a422f4ffd50b6 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 23 Jan 2020 09:07:00 +0100 Subject: [PATCH 118/250] Add polarisation vector as argument to PolarisedSum, clean up of weight parameters using MinuitProxy --- AmpGen/CoherentSum.h | 9 ++-- AmpGen/EventList.h | 14 ++++-- AmpGen/Integrator2.h | 96 ++++++++----------------------------- AmpGen/MinuitParameter.h | 9 ++-- AmpGen/MinuitParameterSet.h | 2 +- AmpGen/PhaseSpace.h | 6 +-- AmpGen/PolarisedSum.h | 7 ++- apps/Generator.cpp | 2 +- src/CoherentSum.cpp | 2 +- src/IncoherentSum.cpp | 1 - src/Integrator2.cpp | 79 ++++++++++++++++++++++++++++++ src/PolarisedSum.cpp | 27 ++++++----- src/Transform.cpp | 9 ++-- 13 files changed, 146 insertions(+), 117 deletions(-) create mode 100644 src/Integrator2.cpp diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index e9ba71b0cb9..deb48641d1d 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -19,13 +19,12 @@ #include "AmpGen/Types.h" #include "AmpGen/Event.h" #include "AmpGen/Projection.h" - +#include "AmpGen/MinuitParameter.h" //#include "AmpGen/functional/pdf.h" namespace AmpGen { class LinearErrorPropagator; - class MinuitParameter; class MinuitParameterSet; class FitFraction; class Particle; @@ -73,8 +72,7 @@ namespace AmpGen void prepare(); void printVal( const Event& evt ); void updateNorms( const std::vector& changedPdfIndices ); - void setWeight( const double& weight ) { m_weight = weight; } - void setWeight( MinuitParameter* param ) { m_weightParam = param; } + void setWeight( MinuitParameter* param ) { m_weight = param; } void makeTotalExpression(); void reset( bool resetEvents = false ); void setEvents( EventList& list ); @@ -98,11 +96,10 @@ namespace AmpGen TransitionMatrix m_total; ///< Total Matrix Element EventList* m_events = {nullptr}; ///< Data events to evaluate PDF on EventType m_evtType; ///< Final state for this amplitude - MinuitParameter* m_weightParam = {nullptr}; ///< Weight parameter (i.e. the normalised yield) size_t m_prepareCalls = {0}; ///< Number of times prepare has been called size_t m_lastPrint = {0}; ///< Last time verbose PDF info was printed size_t m_printFreq = {0}; ///< Frequency to print verbose PDF info - double m_weight = {1}; ///< Weight number (i.e. the normalised yield) + MinuitProxy m_weight = {nullptr, 1}; ///< Weight (i.e. the normalised yield) double m_norm = {0}; ///< Normalisation integral bool m_isConstant = {false}; ///< Flag for a constant PDF bool m_dbThis = {false}; ///< Flag to generate amplitude level debugging diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 3291b2e305a..6dbe21f5b22 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -156,17 +156,25 @@ namespace AmpGen return makeProjection( projection, ArgumentPack(args...) ); } - template EventList& transform( FCN&& fcn ) + template EventList& transform( functor&& fcn ) { for ( auto& event : m_data ) fcn( event ); return *this; } - template void filter( FCN&& fcn ){ - size_t currentSize = size(); + template void filter( functor&& fcn ) + { + unsigned currentSize = size(); m_data.erase( std::remove_if( m_data.begin(), m_data.end(), fcn ) , m_data.end() ); INFO("Filter removes: " << currentSize - size() << " / " << currentSize << " events"); } + + template unsigned count( functor&& fcn ) const + { + unsigned total; + for( const auto& event : *this ) total += fcn(event); + return total; + } }; DECLARE_ARGUMENT(LineColor, int); DECLARE_ARGUMENT(DrawStyle, std::string); diff --git a/AmpGen/Integrator2.h b/AmpGen/Integrator2.h index 212cfef4f13..31f911af72e 100644 --- a/AmpGen/Integrator2.h +++ b/AmpGen/Integrator2.h @@ -7,83 +7,26 @@ namespace AmpGen { class Integrator2 { - private: - static constexpr size_t N = 10; typedef const complex_t& arg; typedef std::function TransferFCN; - size_t m_counter = {0}; - std::array, N> m_integrals; - EventList* m_events = {nullptr}; - std::vector> m_buffer; - std::vector m_weight; - std::map m_index; - void integrateBlock() - { - real_t re[N] = {0}; - real_t im[N] = {0}; - size_t addr_i[N] = {0}; - size_t addr_j[N] = {0}; - for( size_t roll = 0 ; roll < N; ++roll ) - { - addr_i[roll] = m_integrals[roll].i; - addr_j[roll] = m_integrals[roll].j; - } - #pragma omp parallel for reduction(+: re, im) - for ( size_t i = 0; i < m_events->size(); ++i ) { - for ( size_t roll = 0; roll < N; ++roll ) { - auto c = m_buffer[addr_i[roll]][i] * std::conj(m_buffer[addr_j[roll]][i]); - re[roll] += m_weight[i] * std::real(c); - im[roll] += m_weight[i] * std::imag(c); - } - } - real_t nv = m_events->norm(); - for ( size_t j = 0; j < m_counter; ++j ) - m_integrals[j].transfer( complex_t( re[j], im[j] ) / nv ); - m_counter = 0; - } public: - Integrator2( EventList* events = nullptr ) : m_events( events ) - { - if( m_events == nullptr ) return; - m_weight.resize( m_events->size() ); - for( size_t i = 0 ; i < m_events->size(); ++i ) - m_weight[i] = m_events->at(i).weight() / m_events->at(i).genPdf(); - } + explicit Integrator2( const EventList* events = nullptr ); - double sampleNorm() { return m_events->norm(); } - bool isReady() const { return m_events != nullptr; } - EventList& events() { return *m_events; } - const EventList& events() const { return *m_events; } + bool isReady() const; + const EventList& events() const; void queueIntegral(const size_t& c1, const size_t& c2, const size_t& i, const size_t& j, Bilinears* out, - const bool& sim = true) - { - if( !out->workToDo(i,j) ) return; - if( sim ) - addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ - out->set(i,j,val); - if( i != j ) out->set(j,i, std::conj(val) ); } ); - else - addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ out->set(i,j,val); } ); - } - void addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ) - { - m_integrals[m_counter++] = Integral(c1,c2,tFunc); - if ( m_counter == N ) integrateBlock(); - } - void queueIntegral(const size_t& i, const size_t& j, complex_t* result) - { - addIntegralKeyed(i, j, [result](arg& val){ *result = val ; } ); - } - void flush() - { - if ( m_counter == 0 ) return; - integrateBlock(); - } + const bool& sim = true); + void addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ); + void queueIntegral(const size_t& i, const size_t& j, complex_t* result); + void flush(); + void setBuffer( complex_t* pos, const complex_t& value, const size_t& size ); + void setBuffer( complex_t* pos, const std::vector& value, const size_t& size); + template size_t getCacheIndex(const T& expression) const { return m_index.find(expression.name())->second; @@ -112,14 +55,17 @@ namespace AmpGen { setBuffer( &(m_buffer[index][i]), v, vsize ); } } - void setBuffer( complex_t* pos, const complex_t& value, const size_t& size ) - { - *pos = value; - } - void setBuffer( complex_t* pos, const std::vector& value, const size_t& size) - { - memcpy( pos, &(value[0]), size * sizeof(complex_t) ); - } + + private: + static constexpr size_t N = {10}; ///unroll factor + size_t m_counter = {0}; /// + std::array, N> m_integrals; + const EventList* m_events = {nullptr}; + std::vector> m_buffer; + std::vector m_weight; + std::map m_index; + double m_norm = {0}; + void integrateBlock(); }; } #endif diff --git a/AmpGen/MinuitParameter.h b/AmpGen/MinuitParameter.h index 3cecd0ed778..355e6fb3b65 100644 --- a/AmpGen/MinuitParameter.h +++ b/AmpGen/MinuitParameter.h @@ -67,16 +67,15 @@ namespace AmpGen class MinuitProxy { public: - void update() { m_value = m_parameter->mean(); } + void update() { if(m_parameter != nullptr ) m_value = m_parameter->mean(); } MinuitParameter* ptr() { return m_parameter; } - operator double() const { return m_parameter->mean(); } - double getFast() const { return m_value ; } - MinuitProxy( MinuitParameter* param = nullptr ) : m_parameter( param ) { if( m_parameter != nullptr ) update(); } + operator double() const { return m_value; } + MinuitProxy(MinuitParameter* param = nullptr, const double& value=0) : m_parameter(param), m_value(value) { update(); } MinuitParameter* operator->() { return m_parameter; } const MinuitParameter* operator->() const { return m_parameter; } private: + MinuitParameter* m_parameter{nullptr}; double m_value; - MinuitParameter* m_parameter; }; std::ostream& operator<<( std::ostream& os, const MinuitParameter& type ); } // namespace AmpGen diff --git a/AmpGen/MinuitParameterSet.h b/AmpGen/MinuitParameterSet.h index e4aa9bb8187..d0d9f184f9e 100644 --- a/AmpGen/MinuitParameterSet.h +++ b/AmpGen/MinuitParameterSet.h @@ -21,7 +21,7 @@ namespace AmpGen typedef std::vector::const_iterator const_iterator; MinuitParameterSet(); - MinuitParameterSet(const std::vector& params ); + explicit MinuitParameterSet(const std::vector& params ); MinuitParameterSet( const MinuitParameterSet& other ); ~MinuitParameterSet() = default; diff --git a/AmpGen/PhaseSpace.h b/AmpGen/PhaseSpace.h index 7abf796b106..9f462bedc66 100644 --- a/AmpGen/PhaseSpace.h +++ b/AmpGen/PhaseSpace.h @@ -22,9 +22,9 @@ namespace AmpGen class PhaseSpace { public: - PhaseSpace() = default; ///< Empty constructor - PhaseSpace(const EventType& type, TRandom* rand = gRandom); ///< Construct a phase space generator from an EventType - PhaseSpace(const Particle& type, TRandom* rand = gRandom); ///< Construct a phase space generator from a Particle + PhaseSpace() = default; ///< Empty constructor + explicit PhaseSpace(const EventType& type, TRandom* rand = gRandom); ///< Construct a phase space generator from an EventType + explicit PhaseSpace(const Particle& type, TRandom* rand = gRandom); ///< Construct a phase space generator from a Particle bool setDecay( const double& m0, const std::vector& mass ); ///< Set the parameters of this phase space generator void setRandom( TRandom* rand ) { m_rand = rand; } ///< Set the random number used by this phase space generator diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index a60898c1aa7..a5cd898d6c9 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -19,13 +19,13 @@ #include "AmpGen/CoherentSum.h" #include "AmpGen/Expression.h" #include "AmpGen/Tensor.h" +#include "AmpGen/MinuitParameter.h" #include "TMatrixD.h" namespace AmpGen { class LinearErrorPropagator; - class MinuitParameter; class MinuitParameterSet; class FitFraction; class Event; @@ -38,7 +38,7 @@ namespace AmpGen typedef Integrator<10> integrator; PolarisedSum() = default; - PolarisedSum(const EventType&, AmpGen::MinuitParameterSet&, const std::string& = ""); + PolarisedSum(const EventType&, AmpGen::MinuitParameterSet&, const std::vector& = {}); void prepare(); void setEvents(AmpGen::EventList&); void setMC(AmpGen::EventList&); @@ -68,9 +68,8 @@ namespace AmpGen size_t m_nCalls = {0}; real_t m_norm = {1}; EventList* m_events = {nullptr}; - MinuitParameter* m_weightParam = {nullptr}; MinuitParameterSet* m_mps = {nullptr}; - double m_weight = {1}; + MinuitProxy m_weight = {nullptr,1}; std::vector m_pVector = {}; bool m_verbosity = {0}; bool m_debug = {0}; diff --git a/apps/Generator.cpp b/apps/Generator.cpp index ef6d3a566da..fd7ac128e78 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -139,7 +139,7 @@ int main( int argc, char** argv ) signalGenerator.fillEventList( sig, accepted, nEvents ); } else if ( genType == generatorType::TreePhaseSpace ) { - PolarisedSum sig( eventType, MPS, "" ); + PolarisedSum sig( eventType, MPS); std::vector channels; for( auto& chain : sig.matrixElements() ) channels.push_back( chain.decayTree ); Generator signalGenerator(channels, eventType, &rand); diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 5866ff52a0d..e72d0ac3381 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -71,7 +71,6 @@ void updateCache(EventList* events, TransitionMatrix& me, const size_ void CoherentSum::prepare() { - if ( m_weightParam != nullptr ) m_weight = m_weightParam->mean(); if ( m_isConstant && m_prepareCalls != 0 ) return; transferParameters(); std::vector changedPdfIndices; @@ -328,6 +327,7 @@ complex_t CoherentSum::norm(const size_t& x, const size_t& y) const void CoherentSum::transferParameters() { for ( auto& mE : m_matrixElements ) mE.coefficient = mE.coupling(); + m_weight.update(); } void CoherentSum::printVal(const Event& evt) diff --git a/src/IncoherentSum.cpp b/src/IncoherentSum.cpp index 4760c16f6ba..bce1e238814 100644 --- a/src/IncoherentSum.cpp +++ b/src/IncoherentSum.cpp @@ -39,7 +39,6 @@ double IncoherentSum::norm( const Bilinears& norms ) const void IncoherentSum::prepare() { - if ( m_weightParam != nullptr ) m_weight = m_weightParam->mean(); if ( m_isConstant && m_prepareCalls != 0 ) return; transferParameters(); for ( auto& mE : m_matrixElements ) { diff --git a/src/Integrator2.cpp b/src/Integrator2.cpp new file mode 100644 index 00000000000..dacc4902bb4 --- /dev/null +++ b/src/Integrator2.cpp @@ -0,0 +1,79 @@ +#include "AmpGen/Integrator2.h" + +using namespace AmpGen; + +void Integrator2::integrateBlock() +{ + real_t re[N] = {0}; + real_t im[N] = {0}; + size_t addr_i[N] = {0}; + size_t addr_j[N] = {0}; + for( size_t roll = 0 ; roll < N; ++roll ) + { + addr_i[roll] = m_integrals[roll].i; + addr_j[roll] = m_integrals[roll].j; + } +#pragma omp parallel for reduction(+: re, im) + for ( size_t i = 0; i < m_events->size(); ++i ) { + for ( size_t roll = 0; roll < N; ++roll ) { + auto c = m_buffer[addr_i[roll]][i] * std::conj(m_buffer[addr_j[roll]][i]); + re[roll] += m_weight[i] * std::real(c); + im[roll] += m_weight[i] * std::imag(c); + } + } + for ( size_t j = 0; j < m_counter; ++j ) + m_integrals[j].transfer( complex_t( re[j], im[j] ) / m_norm ); + m_counter = 0; +} + +Integrator2::Integrator2( const EventList* events ) : m_events( events ) +{ + if( m_events == nullptr ) return; + m_weight.resize( m_events->size() ); + for( size_t i = 0 ; i < m_events->size(); ++i ) + { + m_weight[i] = m_events->at(i).weight() / m_events->at(i).genPdf(); + m_norm += m_weight[i]; + } +} + +bool Integrator2::isReady() const { return m_events != nullptr; } +const EventList& Integrator2::events() const { return *m_events; } +void Integrator2::queueIntegral(const size_t& c1, + const size_t& c2, + const size_t& i, + const size_t& j, + Bilinears* out, + const bool& sim) +{ + if( !out->workToDo(i,j) ) return; + if( sim ) + addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ + out->set(i,j,val); + if( i != j ) out->set(j,i, std::conj(val) ); } ); + else + addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ out->set(i,j,val); } ); +} +void Integrator2::addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ) +{ + m_integrals[m_counter++] = Integral(c1,c2,tFunc); + if ( m_counter == N ) integrateBlock(); +} +void Integrator2::queueIntegral(const size_t& i, const size_t& j, complex_t* result) +{ + addIntegralKeyed(i, j, [result](arg& val){ *result = val ; } ); +} +void Integrator2::flush() +{ + if ( m_counter == 0 ) return; + integrateBlock(); +} +void Integrator2::setBuffer( complex_t* pos, const complex_t& value, const size_t& size ) +{ + *pos = value; +} + +void Integrator2::setBuffer( complex_t* pos, const std::vector& value, const size_t& size) +{ + memcpy( pos, &(value[0]), size * sizeof(complex_t) ); +} diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 2e4a4ce75df..9e5b5769ee9 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -37,14 +37,14 @@ namespace AmpGen { make_enum(spaceType, spin, flavour) } -PolarisedSum::PolarisedSum( const EventType& type, - MinuitParameterSet& mps, - const std::string& prefix ) +PolarisedSum::PolarisedSum(const EventType& type, + MinuitParameterSet& mps, + const std::vector& pVector) : m_mps (&mps) + , m_pVector (pVector) , m_verbosity (NamedParameter("PolarisedSum::Verbosity", 0 )) , m_debug (NamedParameter("PolarisedSum::Debug" , false )) , m_eventType (type) - , m_prefix (prefix) , m_rules (mps) , m_dim (m_eventType.dim()) { @@ -57,7 +57,7 @@ PolarisedSum::PolarisedSum( const EventType& type, for(const auto& pol : prodPols ) polStates.push_back({pol}); for(unsigned i = 0 ; i != type.size(); ++i ) polStates = indexProduct(polStates, polarisations( type[i] ) ); - auto protoAmps = m_rules.getMatchingRules(m_eventType, m_prefix); + auto protoAmps = m_rules.getMatchingRules(m_eventType); for(const auto& m : protoAmps ) INFO( m.first.uniqueString() ); m_matrixElements.resize( protoAmps.size() ); ThreadPool tp(8); @@ -110,10 +110,13 @@ PolarisedSum::PolarisedSum( const EventType& type, }); } } - auto p = [this](const std::string& name){ return this->m_mps->addOrGet(name, Flag::Fix, 0, 0); }; - if( m_dim.first == 1 ) m_pVector = {}; - else if( m_dim.first == 2 ) m_pVector = {p("Px"), p("Py"), p("Pz")}; - else if( m_dim.first == 3 ) m_pVector = {p("Px"), p("Py"), p("Pz"), p("Tyy"), p("Tzz"), p("Txy"), p("Txz"), p("Tyz")}; + if( m_pVector.size() == 0 ) + { + auto p = [this](const std::string& name){ return this->m_mps->addOrGet(name, Flag::Fix, 0, 0); }; + if( m_dim.first == 1 ) m_pVector = {}; + else if( m_dim.first == 2 ) m_pVector = {p("Px"), p("Py"), p("Pz")}; + else if( m_dim.first == 3 ) m_pVector = {p("Px"), p("Py"), p("Pz"), p("Tyy"), p("Tzz"), p("Txy"), p("Txz"), p("Tyz")}; + } for(size_t i=0; i < m_dim.second * m_dim.first * m_dim.first; ++i) m_norms.emplace_back( m_matrixElements.size(), m_matrixElements.size() ); } @@ -207,7 +210,6 @@ void PolarisedSum::prepare() if( m_nCalls == 0 && m_integrator.isReady() ) m_integIndex.push_back( m_integrator.events().getCacheIndex( t.amp ) ); } if( !m_probExpression.isLinked() ) build_probunnormalised(); - m_weight = m_weightParam == nullptr ? 1 : m_weightParam->mean(); tEval.stop(); ProfileClock tIntegral; m_rho = densityMatrix(m_dim.first, m_pVector); @@ -470,6 +472,7 @@ void PolarisedSum::transferParameters() me.amp.prepare(); } for(auto& p : m_pVector ) p.update(); + m_weight.update(); } real_t PolarisedSum::getValNoCache( const Event& evt ) @@ -484,5 +487,5 @@ real_t PolarisedSum::getValNoCache( const Event& evt ) return m_probExpression( copy.getCachePtr() ); } -void PolarisedSum::setWeight( MinuitParameter* param ){ m_weightParam = param ; } -double PolarisedSum::getWeight() const { return m_weightParam == nullptr ? 1.0 : m_weightParam->mean() ; } +void PolarisedSum::setWeight( MinuitParameter* param ){ m_weight = MinuitProxy(param); } +double PolarisedSum::getWeight() const { return m_weight ; } diff --git a/src/Transform.cpp b/src/Transform.cpp index f498eb98ef1..cd504e38634 100644 --- a/src/Transform.cpp +++ b/src/Transform.cpp @@ -29,11 +29,10 @@ Tensor Transform::sigma_dot_p(const Tensor& p) const Tensor Transform::J_dot_p( const Tensor& p ) const { Expression z(0); - return Tensor( - { z, -p[2], p[1] ,z - , p[2], z, -p[0] ,z - ,-p[1], p[0], z ,z - , z, z, z ,z }, Tensor::dim(4,4) ); + return Tensor( { z, -p[2], p[1] ,z + , p[2], z, -p[0] ,z + ,-p[1], p[0], z ,z + , z, z, z ,z }, Tensor::dim(4,4) ); } Tensor Transform::K_dot_p( const Tensor& p ) const From b510b32d0bb755af5e94834e6bfbdf68ed7e41fe Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 23 Jan 2020 17:28:14 +0100 Subject: [PATCH 119/250] Add proper destructor for MinuitParameterSet --- AmpGen/Minimiser.h | 12 ++++++------ AmpGen/MinuitParameterSet.h | 2 +- src/MinuitParameterSet.cpp | 6 ++++++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/AmpGen/Minimiser.h b/AmpGen/Minimiser.h index 9400f3c3c99..c32c45921b9 100644 --- a/AmpGen/Minimiser.h +++ b/AmpGen/Minimiser.h @@ -85,12 +85,12 @@ namespace AmpGen std::function m_theFunction; ROOT::Minuit2::Minuit2Minimizer* m_minimiser = {nullptr}; std::vector m_covMatrix = {0}; - std::vector m_mapping = {}; - int m_status = {0}; - unsigned int m_nParams = {0}; - unsigned int m_printLevel = {0}; - double m_ll_zero = {0}; - bool m_normalise = {false}; + std::vector m_mapping = {}; + int m_status = {0}; + unsigned m_nParams = {0}; + unsigned m_printLevel = {0}; + double m_ll_zero = {0}; + bool m_normalise = {false}; std::vector m_extendedTerms; }; } // namespace AmpGen diff --git a/AmpGen/MinuitParameterSet.h b/AmpGen/MinuitParameterSet.h index d0d9f184f9e..149d4f1aef8 100644 --- a/AmpGen/MinuitParameterSet.h +++ b/AmpGen/MinuitParameterSet.h @@ -23,7 +23,7 @@ namespace AmpGen MinuitParameterSet(); explicit MinuitParameterSet(const std::vector& params ); MinuitParameterSet( const MinuitParameterSet& other ); - ~MinuitParameterSet() = default; + ~MinuitParameterSet(); // = default; MinuitParameterSet getFloating(); diff --git a/src/MinuitParameterSet.cpp b/src/MinuitParameterSet.cpp index f792a31d672..33fe894f296 100644 --- a/src/MinuitParameterSet.cpp +++ b/src/MinuitParameterSet.cpp @@ -247,3 +247,9 @@ double MinuitParameterSet::operator()( const std::string& name ) } return m_keyAccess[name]->mean(); } + +MinuitParameterSet::~MinuitParameterSet() +{ + for( auto& param : m_parameters ) delete param; + +} From 2a3ab309e1d8d1c9d7ff61650757c28397b9684d Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 26 Jan 2020 12:27:57 +0100 Subject: [PATCH 120/250] Add export to CMakeLists such that AmpGen can be used with find_package --- AmpGen/CoherentSum.h | 2 +- AmpGen/EventList.h | 2 +- AmpGen/Integrator2.h | 2 +- AmpGen/PolarisedSum.h | 2 +- AmpGenConfig.cmake.in | 18 +++++++++++ Standalone.cmake | 71 ++++++++++++++++++------------------------- src/PolarisedSum.cpp | 2 +- test/CMakeLists.txt | 24 +++++++++++++++ 8 files changed, 77 insertions(+), 46 deletions(-) create mode 100644 AmpGenConfig.cmake.in create mode 100644 test/CMakeLists.txt diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index deb48641d1d..0ceff448770 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -72,7 +72,7 @@ namespace AmpGen void prepare(); void printVal( const Event& evt ); void updateNorms( const std::vector& changedPdfIndices ); - void setWeight( MinuitParameter* param ) { m_weight = param; } + void setWeight( MinuitProxy param ) { m_weight = param; } void makeTotalExpression(); void reset( bool resetEvents = false ); void setEvents( EventList& list ); diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 6dbe21f5b22..fd90a5a6d47 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -171,7 +171,7 @@ namespace AmpGen template unsigned count( functor&& fcn ) const { - unsigned total; + unsigned total = 0; for( const auto& event : *this ) total += fcn(event); return total; } diff --git a/AmpGen/Integrator2.h b/AmpGen/Integrator2.h index 31f911af72e..d8f7742c37d 100644 --- a/AmpGen/Integrator2.h +++ b/AmpGen/Integrator2.h @@ -4,7 +4,7 @@ #include "AmpGen/Integrator.h" namespace AmpGen { - + /// test /// class Integrator2 { typedef const complex_t& arg; diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index a5cd898d6c9..a6c002ac73b 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -45,7 +45,7 @@ namespace AmpGen void reset(const bool& = false); void debug(const AmpGen::Event&); void debug_norm(); - void setWeight(MinuitParameter*); + void setWeight(MinuitProxy); double getWeight() const; void calculateNorms(const std::vector&); void generateSourceCode(const std::string&, const double& = 1, bool = false); diff --git a/AmpGenConfig.cmake.in b/AmpGenConfig.cmake.in new file mode 100644 index 00000000000..01d34c5eeec --- /dev/null +++ b/AmpGenConfig.cmake.in @@ -0,0 +1,18 @@ +# - Config file for the AmpGen package +# It defines the following variables +# AMPGEN_INCLUDE_DIRS - include directories for AmpGen +# AMPGEN_LIBRARIES - libraries to link against +# AMPGEN_EXECUTABLE - the bar executable + +# Compute paths +get_filename_component(AMPGEN_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +set(AMPGEN_INCLUDE_DIRS "@PROJECT_SOURCE_DIR@") +set(USE_OPENMP "@USE_OPENMP@") +# Our library dependencies (contains definitions for IMPORTED targets) +if(NOT TARGET AmpGen AND NOT AmpGen_BINARY_DIR) + include("@CMAKE_BINARY_DIR@/AmpGenTargets.cmake") +endif() + +# These are IMPORTED targets created by FooBarTargets.cmake +set(AMPGEN_LIBRARIES AmpGen) + diff --git a/Standalone.cmake b/Standalone.cmake index 8828b12f415..0e59713c101 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -1,34 +1,39 @@ -set(AMPGEN_CXX ${CMAKE_CXX_COMPILER} CACHE FILEPATH "This should be the path to compiler (use which c++ for macOS)" ) +set(AMPGEN_CXX ${CMAKE_CXX_COMPILER} CACHE FILEPATH "This should be the path to compiler (use which c++ for macOS)" ) + +file(TO_CMAKE_PATH "${PROJECT_BINARY_DIR}/CMakeLists.txt" LOC_PATH) +if(EXISTS "${LOC_PATH}") + message(FATAL_ERROR "You cannot build in a source directory (or any directory with a CMakeLists.txt file). Please make a build subdirectory. Feel free to remove CMakeCache.txt and CMakeFiles.") +endif() file(GLOB_RECURSE AMPGEN_SRC src/*) file(GLOB_RECURSE AMPGEN_HDR AmpGen/*) if( NOT "${CMAKE_CXX_STANDARD}" ) - set(CMAKE_CXX_STANDARD 14) + set(CMAKE_CXX_STANDARD 17) endif() SET(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") -message(STATUS "USE_OPENMP = ${USE_OPENMP}") - set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin") +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/bin") -set(CMAKE_TEST_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/test") +set(CMAKE_TEST_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/test") include(CMakeDependentOption) include(CMakePrintHelpers) +include(GNUInstallDirs) option(AMPGEN_DEBUG "AmpGen Debug printout") option(AMPGEN_TRACE "AmpGen Trace printout") configure_file ("${PROJECT_SOURCE_DIR}/AmpGen/Version.h.in" "${CMAKE_BINARY_DIR}/AmpGenVersion.h") -add_library(AmpGen SHARED ${AMPGEN_SRC} ${AMPGEN_HDR}) +add_library(${PROJECT_NAME} SHARED ${AMPGEN_SRC} ${AMPGEN_HDR}) +add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) if(DEFINED ENV{ROOTSYS}) list(APPEND CMAKE_MODULE_PATH "$ENV{ROOTSYS}/etc/cmake/") @@ -53,10 +58,9 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() -message( STATUS "ROOT_INCLUDE_DIRS = ${ROOT_INCLUDE_DIRS}") +target_include_directories(AmpGen PUBLIC $ + $ ) -target_include_directories(AmpGen PUBLIC "${CMAKE_SOURCE_DIR}") -target_include_directories(AmpGen PUBLIC "${CMAKE_BINARY_DIR}") target_include_directories(AmpGen SYSTEM PUBLIC "${ROOT_INCLUDE_DIRS}") target_link_libraries(AmpGen PUBLIC ${ROOT_LIBRARIES} ${CMAKE_DL_LIBS}) @@ -114,14 +118,14 @@ if(AMPGEN_XROOTD) endif() target_compile_definitions(AmpGen - PUBLIC + INTERFACE "AMPGENROOT_CMAKE=\"${CMAKE_BINARY_DIR}/bin\"" "AMPGEN_CXX=\"${AMPGEN_CXX}\"" $<$:DEBUGLEVEL=1> $<$:TRACELEVEL=1>) target_compile_options(AmpGen - PUBLIC + INTERFACE -Wall -Wextra -Wpedantic -g3 -Wno-unused-parameter -Wno-unknown-pragmas @@ -139,7 +143,7 @@ file(GLOB_RECURSE examples examples/*.cpp ) foreach( file ${applications} ) get_filename_component( Executable ${file} NAME_WE ) - cmake_print_variables(Executable) + # cmake_print_variables(Executable) add_executable(${Executable} ${file}) target_compile_options(${Executable} PUBLIC -g3 -Ofast) target_link_libraries(${Executable} PUBLIC AmpGen) @@ -147,7 +151,7 @@ endforeach() foreach( file ${examples} ) get_filename_component( Executable ${file} NAME_WE ) - cmake_print_variables(Executable) + # cmake_print_variables(Executable) add_executable(${Executable} ${file}) target_link_libraries(${Executable} PUBLIC AmpGen) endforeach() @@ -156,31 +160,16 @@ file(GLOB_RECURSE options_files options/*.*) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/bin") foreach(file ${options_files}) get_filename_component(OptionFile "${file}" NAME) - cmake_print_variables(OptionFile) + # cmake_print_variables(OptionFile) execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${file}" "${CMAKE_BINARY_DIR}/bin/${OptionFile}") endforeach() -enable_testing() -set(Boost_NO_BOOST_CMAKE ON) - -find_package(Boost 1.67.0 COMPONENTS unit_test_framework) -if ( Boost_FOUND ) - include_directories (${Boost_INCLUDE_DIRS}) - file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cpp) - foreach(testSrc ${TEST_SRCS}) - get_filename_component(testName ${testSrc} NAME_WE) - add_executable(${testName} ${testSrc}) - set_target_properties(${testName} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_TEST_OUTPUT_DIRECTORY}" - RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_TEST_OUTPUT_DIRECTORY}" - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_TEST_OUTPUT_DIRECTORY}" - EXECUTABLE_OUTPUT_DIRECTORY "${CMAKE_TEST_OUTPUT_DIRECTORY}" - ) - target_link_libraries(${testName} PUBLIC ${Boost_LIBRARIES} AmpGen) - add_test(NAME ${testName} WORKING_DIRECTORY ${CMAKE_TEST_OUTPUT_DIRECTORY} COMMAND ${CMAKE_TEST_OUTPUT_DIRECTORY}/${testName} ) - endforeach(testSrc) -else() - message( WARNING "Warning: Boost (version >= 1.67.0) required to build unit tests\n") -endif() +add_subdirectory(test) + +include(CMakePackageConfigHelpers) +write_basic_package_version_file(AmpGenVersion.cmake VERSION ${PACKAGE_VERSION} COMPATIBILITY AnyNewerVersion) +configure_file(AmpGenConfig.cmake.in AmpGenConfig.cmake) # @ONLY) +export( TARGETS AmpGen NAMESPACE AmpGen:: FILE AmpGenTargets.cmake ) +set(CMAKE_EXPORT_PACKAGE_REGISTRY ON) +export(PACKAGE AmpGen) diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 9e5b5769ee9..33d9686c9f4 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -487,5 +487,5 @@ real_t PolarisedSum::getValNoCache( const Event& evt ) return m_probExpression( copy.getCachePtr() ); } -void PolarisedSum::setWeight( MinuitParameter* param ){ m_weight = MinuitProxy(param); } +void PolarisedSum::setWeight( MinuitProxy param ){ m_weight = param; } double PolarisedSum::getWeight() const { return m_weight ; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 00000000000..2d2b93dba9d --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,24 @@ + +enable_testing() +set(Boost_NO_BOOST_CMAKE ON) + +find_package(Boost 1.67.0 COMPONENTS unit_test_framework) +if ( Boost_FOUND ) + include_directories (${Boost_INCLUDE_DIRS}) + file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cpp) + foreach(testSrc ${TEST_SRCS}) + get_filename_component(testName ${testSrc} NAME_WE) + add_executable(${testName} ${testSrc}) + set_target_properties(${testName} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_TEST_OUTPUT_DIRECTORY}" + RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_TEST_OUTPUT_DIRECTORY}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_TEST_OUTPUT_DIRECTORY}" + EXECUTABLE_OUTPUT_DIRECTORY "${CMAKE_TEST_OUTPUT_DIRECTORY}" + ) + target_link_libraries(${testName} PUBLIC ${Boost_LIBRARIES} AmpGen) + add_test(NAME ${testName} WORKING_DIRECTORY ${CMAKE_TEST_OUTPUT_DIRECTORY} COMMAND ${CMAKE_TEST_OUTPUT_DIRECTORY}/${testName} ) + endforeach(testSrc) +else() + message( WARNING "Warning: Boost (version >= 1.67.0) required to build unit tests\n") +endif() From 60668b6acfcf0b566eeadb7f46bbb088f989862c Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 26 Jan 2020 13:07:10 +0100 Subject: [PATCH 121/250] Fix AMPGEN_CXX being added to CMakeLists.txt --- Standalone.cmake | 4 ++-- src/CompilerWrapper.cpp | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Standalone.cmake b/Standalone.cmake index 0e59713c101..96e84405fb5 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -117,10 +117,10 @@ if(AMPGEN_XROOTD) target_link_libraries(AmpGen PUBLIC ${XROOTD_LIB}) endif() -target_compile_definitions(AmpGen - INTERFACE +target_compile_definitions(AmpGen PRIVATE "AMPGENROOT_CMAKE=\"${CMAKE_BINARY_DIR}/bin\"" "AMPGEN_CXX=\"${AMPGEN_CXX}\"" + "USE_OPENMP=\"${USE_OPENMP}\"" $<$:DEBUGLEVEL=1> $<$:TRACELEVEL=1>) diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index c6eceaa4c23..ed0992f8ab3 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -21,6 +21,11 @@ #include "AmpGenVersion.h" using namespace AmpGen; +#ifdef AMPGEN_CXX +#pragma message "Using c++ compiler: " AMPGEN_CXX " for JIT" +#else +#pragma warning "No AMPGEN_CXX for JIT set" +#endif CompilerWrapper::CompilerWrapper( const bool& verbose ) : m_verbose(verbose), From f41b7d95dda6368a4b36fba2c63ed16051cf135d Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 28 Jan 2020 09:13:49 +0100 Subject: [PATCH 122/250] Update masses and widths of D*(2300) and D*(2460) match PDG2020 --- AmpGen/EventList.h | 4 +--- options/mass_width.csv | 8 ++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index fd90a5a6d47..01e739042ba 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -171,9 +171,7 @@ namespace AmpGen template unsigned count( functor&& fcn ) const { - unsigned total = 0; - for( const auto& event : *this ) total += fcn(event); - return total; + return std::count_if( std::begin(*this), std::end(*this), fcn ); } }; DECLARE_ARGUMENT(LineColor, int); diff --git a/options/mass_width.csv b/options/mass_width.csv index 4d32b4ebd45..4833cbc1c7e 100644 --- a/options/mass_width.csv +++ b/options/mass_width.csv @@ -369,13 +369,13 @@ 1.86484E+03 ,1.7E-01,1.7E-01,1.605E-09 ,6.0E-12,6.0E-12,1/2, ,0 ,-, ,F, 421, 0, ,R,D ,cU 2.00697E+03 ,1.9E-01,1.9E-01,9.6E-02 ,-1 ,-1 ,1/2, ,1 ,-, ,F, 423, 0, ,R,D*(2007) ,cU 2.01027E+03 ,1.7E-01,1.7E-01,9.6E-02 ,2.2E-02,2.2E-02,1/2, ,1 ,-, ,B, 413, +, ,R,D*(2010) ,cD -2.35E+03 ,5.0E+01,5.0E+01,2.6E+02 ,5.0E+01,5.0E+01,1/2, ,0 ,+, ,F, 10421, 0, ,S,D(0)*(2400) ,cU -2.40E+03 ,4.0E+01,4.0E+01,2.8E+02 ,4.0E+01,4.0E+01,1/2, ,0 ,+, ,F, 10411, +, ,S,D(0)*(2400) ,cD +2.30E+03 ,1.9E+01,1.9E+01,2.74E+02 ,4.0E+01,4.0E+01,1/2, ,0 ,+, ,F, 10421, 0, ,S,D(0)*(2300) ,cU +2.349E+03 ,7.0E+00,7.0E+00,2.21E+02 ,1.8E+01,1.8E+01,1/2, ,0 ,+, ,F, 10411, +, ,S,D(0)*(2300) ,cD 2.4223E+03 ,1.3E+00,1.3E+00,2.04E+01 ,1.7E+00,1.7E+00,1/2, ,1 ,+, ,F, 10423, 0, ,R,D(1)(2420) ,cU 2.4234E+03 ,3.1E+00,3.1E+00,2.5E+01 ,6.0E+00,6.0E+00,1/2, ,? ,?, ,B, 10413, +, ,S,D(1)(2420) ,cD 2.43E+03 ,4.0E+01,4.0E+01,3.8E+02 ,1.3E+02,1.1E+02,1/2, ,1 ,+, ,F, 20423, 0, ,S,D(1)(2430) ,cU -2.4611E+03 ,1.6E+00,1.6E+00,4.3E+01 ,4.0E+00,4.0E+00,1/2, ,2 ,+, ,F, 425, 0, ,R,D(2)*(2460) ,cU -2.4601E+03 ,2.6E+00,3.5E+00,3.7E+01 ,6.0E+00,6.0E+00,1/2, ,2 ,+, ,B, 415, +, ,R,D(2)*(2460) ,cD +2.4607E+03 ,0.4E+00,0.4E+00,4.75E+01 ,1.1E+00,1.1E+00,1/2, ,2 ,+, ,F, 425, 0, ,R,D(2)*(2460) ,cU +2.4654E+03 ,1.3E+00,1.3E+00,4.67E+01 ,1.2E+00,1.2E+00,1/2, ,2 ,+, ,B, 415, +, ,R,D(2)*(2460) ,cD 2.637E+03 ,6.0E+00,6.0E+00,15 ,-1 ,-1 ,1/2, ,? ,?, ,F, , +, ,S,D*(2640) ,cD 1.96849E+03 ,3.4E-01,3.4E-01,1.325E-09 ,1.9E-11,1.9E-11,0 , ,0 ,-, ,B, 431, +, ,R,D(s) ,cS 2.1123E+03 ,5.0E-01,5.0E-01,1.0E-01 ,-1 ,-1 ,0 , ,1 ,-, ,B, 433, +, ,R,D(s)* ,cS From 39fc83eeb0ee63ea8677fb4fd892c11e945df5fd Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 31 Jan 2020 16:30:33 +0100 Subject: [PATCH 123/250] Add Chew-Mandelstam parameterisation of self-energy for K-matrix --- src/Lineshapes/CoupledChannel.cpp | 18 ++++++++++++++++-- src/Lineshapes/GenericKmatrix.cpp | 13 +++++++------ src/PolarisedSum.cpp | 3 +++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/Lineshapes/CoupledChannel.cpp b/src/Lineshapes/CoupledChannel.cpp index 1fb61d77549..8ef1ea6a2cc 100644 --- a/src/Lineshapes/CoupledChannel.cpp +++ b/src/Lineshapes/CoupledChannel.cpp @@ -11,6 +11,7 @@ using namespace AmpGen; using namespace AmpGen::fcn; +using namespace std::complex_literals; Expression H(const Expression& x, const Expression& y, @@ -76,10 +77,23 @@ Expression AmpGen::phaseSpace(const Expression& s, const Particle& p, const size } if( phsp_parameterisation == std::string("arXiv.0707.3596") ){ INFO("Got AS parametrisation"); - Expression E = 1; - // return 2*fpow(k2,l)*complex_sqrt(k2) * E * 2 / ((1.5+k2p) * sqrt(s) ); return 2 * complex_sqrt(k2/s); } + if( phsp_parameterisation == std::string("CM") ) + { + if( l != 0 ){ + WARNING("Chew-Mandelstam only implemented for l=0"); + } + auto m1 = p.daughter(0)->mass(); + auto m2 = p.daughter(1)->mass(); + Expression s1 = m1*m1; + Expression s2 = m2*m2; + Expression sT = (m1+m2)*(m1+m2); + Expression q2 = (s*s + s1*s1 + s2*s2 - 2*s*s1 - 2*s*s2 - 2*s1*s2)/(4*s); + auto q = fcn::complex_sqrt(q2); + auto arg = (s1 + s2 - s + 2*fcn::sqrt(s) * q )/ (2*m1*m2); + return (2.*q * fcn::log(arg) / fcn::sqrt(s) - (s1-s2)*( 1./s - 1./sT ) * fcn::log(m1/m2) ) / ( 16.i * M_PI * M_PI ); + } } if( fs.size() == 3 && ! p.daughter(0)->isStable() ) return rho_threeBody( s, *p.daughter(0), *p.daughter(1) ); if( fs.size() == 3 && ! p.daughter(1)->isStable() ) return rho_threeBody( s, *p.daughter(1), *p.daughter(0) ); diff --git a/src/Lineshapes/GenericKmatrix.cpp b/src/Lineshapes/GenericKmatrix.cpp index c849465533e..a6276f4156b 100644 --- a/src/Lineshapes/GenericKmatrix.cpp +++ b/src/Lineshapes/GenericKmatrix.cpp @@ -35,21 +35,21 @@ DEFINE_LINESHAPE(GenericKmatrix) auto s0 = mass*mass; ADD_DEBUG(s, dbexpressions ); ADD_DEBUG(s0, dbexpressions ); - INFO("Initialising K-matrix with : " << nChannels); + INFO("Initialising K-matrix with [nChannels = " << nChannels << ", nPoles = " << nPoles << "]"); for( unsigned i = 0 ; i < channels.size(); i+=1 ){ Particle p( channels[i] ); INFO( p.decayDescriptor() ); - Expression sf = Parameter( lineshapeModifier + "::phsp::sf::"+std::to_string(i+1), 1); - phsps.emplace_back( sf * phaseSpace(s, p, p.L() ) ); - bw_phase_space.emplace_back( sf * phaseSpace(s0, p, p.L() ) ); - ADD_DEBUG( *phsps.rbegin(), dbexpressions); - ADD_DEBUG( phaseSpace(s0,p,p.L()), dbexpressions ); + phsps.emplace_back( phaseSpace(s, p, p.L() ) ); + bw_phase_space.emplace_back( phaseSpace(s0, p, p.L() ) ); + if( dbexpressions != nullptr ) dbexpressions->emplace_back("phsp_"+p.decayDescriptor(), *phsps.rbegin() ); //ADD_DEBUG( *phsps.rbegin(), dbexpressions); +// ADD_DEBUG( phaseSpace(s0,p,p.L()), dbexpressions ); } Tensor non_resonant( Tensor::dim(nChannels, nChannels) ); std::vector poleConfigs; for (unsigned pole = 1; pole <= nPoles; ++pole ){ std::string stub = lineshapeModifier + "::pole::" + std::to_string(pole); Expression mass = Parameter(stub + "::mass"); + INFO( "Will link to parameter: " << stub + "::mass"); poleConfig thisPole(mass*mass); if( dbexpressions != nullptr ) dbexpressions->emplace_back(stub+"::mass", mass); Expression bw_width = 0; @@ -57,6 +57,7 @@ DEFINE_LINESHAPE(GenericKmatrix) for (unsigned channel = 1; channel <= nChannels; ++channel ) { Expression g = Parameter(stub+"::g::"+std::to_string(channel)); + INFO("Will link to parameter: " << stub+"::g::"+std::to_string(channel) ); thisPole.add(g, 1); if( dbexpressions != nullptr ){ dbexpressions->emplace_back( stub+"::g::"+std::to_string(channel), g); diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 33d9686c9f4..7e043acd18e 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -73,6 +73,7 @@ PolarisedSum::PolarisedSum(const EventType& type, p.setPolarisationState( polStates[j] ); thisExpression[j] = make_cse( p.getExpression(&syms) ); } + INFO("Got: " << syms.size() << " debugging symbols"); m_matrixElements[i] = TransitionMatrix>( p, coupling, @@ -350,8 +351,10 @@ void PolarisedSum::debug(const Event& evt) for(auto& me : m_matrixElements){ auto values = me(copy); copy.setCache( values , me.addressData ); + me.amp.debug( copy.address() ); } m_probExpression.debug( copy.getCachePtr() ); + } } From e20488e6ddde8da8d3246cb991c7ac11806445e6 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 4 Feb 2020 11:25:51 +0100 Subject: [PATCH 124/250] Add OSX travis configuration --- .ci/build_docs.sh | 2 ++ .ci/travis.sh | 1 + .travis.yml | 4 ++++ src/PolarisedSum.cpp | 1 - 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.ci/build_docs.sh b/.ci/build_docs.sh index 35d6588bb29..9a8453ba881 100644 --- a/.ci/build_docs.sh +++ b/.ci/build_docs.sh @@ -34,6 +34,8 @@ __AUTHOR__="Jeroen de Bruijn" ################################################################################ ##### Setup this script and get the current gh-pages branch. ##### +if [[ $TRAVIS_OS_NAME == "osx" ]]; then return ; fi + echo 'Setting up the script...' # Exit with nonzero exit code if anything fails set -e diff --git a/.ci/travis.sh b/.ci/travis.sh index 17a9ddedce0..f72db1ad5ea 100644 --- a/.ci/travis.sh +++ b/.ci/travis.sh @@ -1,5 +1,6 @@ echo -en 'travis_fold:start:script.build\\r' echo "Building..." +echo "Building under OS: $TRAVIS_OS_NAME" set -evx mkdir -p build diff --git a/.travis.yml b/.travis.yml index 02705555df0..64592e0c52e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,8 @@ sudo: false +os: + - linux + - osx + dist: xenial cache: diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 7e043acd18e..c4ac3ab2a7a 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -73,7 +73,6 @@ PolarisedSum::PolarisedSum(const EventType& type, p.setPolarisationState( polStates[j] ); thisExpression[j] = make_cse( p.getExpression(&syms) ); } - INFO("Got: " << syms.size() << " debugging symbols"); m_matrixElements[i] = TransitionMatrix>( p, coupling, From a8587c1ecf012676fe08509d4af6887aabe28016 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 4 Feb 2020 11:59:58 +0100 Subject: [PATCH 125/250] dumb down build_root for osx --- .ci/build_root.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.ci/build_root.sh b/.ci/build_root.sh index 6f7612e3a7c..a07cdd4fcdd 100644 --- a/.ci/build_root.sh +++ b/.ci/build_root.sh @@ -1,6 +1,7 @@ set -evx -pushd "${DEPS_DIR}" +old_pwd=$PWD +cd $DEPS_DIR # root_v6.12.06.Linux-ubuntu16-x86_64-gcc5.4.tar.gz ROOT_URL="https://root.cern.ch/download/root_v6.12.06.Linux-ubuntu16-x86_64-gcc5.4.tar.gz" @@ -12,6 +13,7 @@ if [[ ! -f "${DEPS_DIR}/root/bin/root-config" ]] ; then fi source "${DEPS_DIR}/root/bin/thisroot.sh" -popd +# popd +cd $old_pwd set +evx From 4f4d2f69b85e3166972b3b4055431c905c1ebf16 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 4 Feb 2020 12:16:25 +0100 Subject: [PATCH 126/250] trying to fix travis.yml for osx --- .travis.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 64592e0c52e..fa5bbe03951 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,11 @@ os: - linux - osx -dist: xenial +# dist: xenial +compiler: + - gcc + - clang + cache: ccache: true @@ -36,6 +40,8 @@ addons: - libtbb-dev before_install: +- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update ; fi +- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install graphviz; fi - source .ci/build_root.sh # Build your code e.g. by calling make From 6b24c3d74aa4fcf76a39e31bce923540663d9f6d Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 4 Feb 2020 12:17:55 +0100 Subject: [PATCH 127/250] skip building root for osx --- .ci/build_root.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.ci/build_root.sh b/.ci/build_root.sh index a07cdd4fcdd..7b71f79c418 100644 --- a/.ci/build_root.sh +++ b/.ci/build_root.sh @@ -1,3 +1,6 @@ + +if [["$TRAVIS_OS_NAME" = "osx" ]] ; then return; fi + set -evx old_pwd=$PWD From a588f0dd9ce4963accbf64e465279fcc96930090 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 4 Feb 2020 16:57:58 +0100 Subject: [PATCH 128/250] Fix to have parameter expressions of complex parameters in complex coordinates --- AmpGen/AmplitudeRules.h | 1 + AmpGen/ExpressionParser.h | 9 ++++++++- src/AmplitudeRules.cpp | 6 ------ src/ExpressionParser.cpp | 28 +++++++++++++++++++++++++--- src/MinuitParameterSet.cpp | 1 + 5 files changed, 35 insertions(+), 10 deletions(-) diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index 67207260016..71436e4bda3 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -13,6 +13,7 @@ #include "AmpGen/CompiledExpression.h" #include "AmpGen/Event.h" #include "AmpGen/Particle.h" +#include "AmpGen/ExpressionParser.h" namespace AmpGen { diff --git a/AmpGen/ExpressionParser.h b/AmpGen/ExpressionParser.h index 7932bcc94e0..0c69776b8b0 100644 --- a/AmpGen/ExpressionParser.h +++ b/AmpGen/ExpressionParser.h @@ -9,13 +9,17 @@ #include "AmpGen/Expression.h" #include "AmpGen/Types.h" +#include "AmpGen/enum.h" namespace AmpGen { class ASTResolver; class MinuitParameter; class MinuitParameterSet; - + + declare_enum(coordinateType, cartesian, polar) + declare_enum(angType, deg, rad) + class MinuitParameterLink : public IExpression { public: explicit MinuitParameterLink( MinuitParameter* param ) ; @@ -82,6 +86,9 @@ namespace AmpGen std::map m_unaryFunctions; std::vector> m_binaryFunctions; + bool m_isCartesian = {true}; + double m_sf = {1}; + }; } // namespace AmpGen diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index 79592f57307..0a14362c65f 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -18,12 +18,6 @@ using namespace AmpGen; using namespace std::complex_literals; -namespace AmpGen -{ - make_enum(coordinateType, cartesian, polar) - make_enum(angType, deg, rad) -} - Coupling::Coupling(MinuitParameter* re, MinuitParameter* im) : m_re(re), m_im(im) diff --git a/src/ExpressionParser.cpp b/src/ExpressionParser.cpp index 5562c5d60a1..a214c9a6af1 100644 --- a/src/ExpressionParser.cpp +++ b/src/ExpressionParser.cpp @@ -9,6 +9,8 @@ #include "AmpGen/Utilities.h" #include "AmpGen/MinuitParameter.h" #include "AmpGen/ASTResolver.h" +#include "AmpGen/enum.h" +#include "AmpGen/NamedParameter.h" using namespace AmpGen; using namespace std::complex_literals; @@ -16,6 +18,12 @@ using namespace std::complex_literals; DEFINE_CAST( MinuitParameterLink ) DEFINE_CAST( ExpressionPack ) +namespace AmpGen +{ + complete_enum(coordinateType, cartesian, polar) + complete_enum(angType, deg, rad) +} + void ExpressionParser::processBinaryOperators( std::vector& opCodes, std::vector& expressions ) { for ( auto& fcn : m_binaryFunctions ) { @@ -109,8 +117,21 @@ ExpressionParser::ExpressionParser() add_binary( "+" , [](auto& A, auto& B ) { return A + B; } ); add_binary( ">" , [](auto& A, auto& B ) { return A > B; } ); add_binary( "<" , [](auto& A, auto& B ) { return A < B; } ); - add_binary( "&&", []( auto& A, auto& B ) { return A && B; } ); - add_binary( "," , []( auto& A, auto& B ) { return ExpressionPack( A, B ); } ); + add_binary( "&&", [](auto& A, auto& B ) { return A && B; } ); + add_binary( "," , [](auto& A, auto& B ) { return ExpressionPack( A, B ); } ); + + coordinateType coord = NamedParameter("CouplingConstant::Coordinates", coordinateType::cartesian); + angType degOrRad = NamedParameter("CouplingConstant::AngularUnits", angType::rad); + m_isCartesian = true; + if( coord == coordinateType::polar ) m_isCartesian = false; + else if ( coord != coordinateType::cartesian){ + FATAL("Coordinates for coupling constants must be either cartesian or polar"); + } + if ( degOrRad == angType::deg) m_sf = M_PI / 180; + else if ( degOrRad != angType::rad){ + FATAL("CouplingConstant::AngularUnits must be either rad or deg"); + } + } Expression ExpressionParser::parse( @@ -142,7 +163,8 @@ Expression ExpressionParser::processEndPoint( const std::string& name, const Min auto it = mps->find(name); if ( it != nullptr ) return MinuitParameterLink( it ); else if ( mps->find(name+"_Re") != nullptr && mps->find(name+"_Im") != nullptr ) { - return MinuitParameterLink( mps->find(name+"_Re") ) + 1i * MinuitParameterLink( mps->find(name+"_Im") ); + if( m_isCartesian ) return MinuitParameterLink( mps->find(name+"_Re") ) + 1i * MinuitParameterLink( mps->find(name+"_Im") ); + else return MinuitParameterLink( mps->find(name+"_Re") ) * fcn::exp( m_sf * 1i *MinuitParameterLink( mps->find(name+"_Im") ) ); } else { WARNING( "Token not understood: " << name << " [map size = " << mps->size() << "]" ); diff --git a/src/MinuitParameterSet.cpp b/src/MinuitParameterSet.cpp index 33fe894f296..c2a08ae0905 100644 --- a/src/MinuitParameterSet.cpp +++ b/src/MinuitParameterSet.cpp @@ -227,6 +227,7 @@ MinuitParameter* MinuitParameterSet::addOrGet( const std::string& name, const Fl if ( m_keyAccess.count( name ) != 0 ) return m_keyAccess[name]; return add( name, flag, mean, sigma, min, max ); } + MinuitParameterSet::const_iterator MinuitParameterSet::cbegin() const { return m_parameters.cbegin(); } MinuitParameterSet::const_iterator MinuitParameterSet::cend() const { return m_parameters.cend(); } MinuitParameterSet::iterator MinuitParameterSet::begin() { return m_parameters.begin(); } From e28a417f4907cd11fed3e0106008361c900294f7 Mon Sep 17 00:00:00 2001 From: Paras Naik Date: Tue, 4 Feb 2020 20:12:18 +0000 Subject: [PATCH 129/250] Minor changes to CompilerWrapper to help with troubleshooting. --- src/CompilerWrapper.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index ed0992f8ab3..3bf88ed9781 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -34,13 +34,17 @@ CompilerWrapper::CompilerWrapper( const bool& verbose ) : if ( m_cxx == "" ) { #ifdef AMPGEN_CXX if( m_verbose ) - INFO( "Using original compiler; set global variable CXX if another needed: " << AMPGEN_CXX ); + INFO( "Global variable CXX is undefined, using compiler variable AMPGEN_CXX: " << AMPGEN_CXX ); m_cxx = AMPGEN_CXX; #else m_cxx = getenv("AMPGEN_CXX") != nullptr ? std::string( getenv( "AMPGEN_CXX" ) ) : ""; if( m_cxx == "" ) ERROR( "No configured compiler; set global variable CXX" ); #endif } + else { + if( m_verbose ) + INFO( "Global variable CXX is defined: " << m_cxx << "; AMPGEN_CXX is ignored" ); // to use AMPGEN_CXX, unset CXX + } } void CompilerWrapper::generateSource( const CompiledExpressionBase& expression, const std::string& filename ) @@ -133,7 +137,7 @@ void CompilerWrapper::compileSource( const std::string& fname, const std::string "-rdynamic", "-fPIC"}; std::transform( compile_flags.begin(), compile_flags.end(), std::back_inserter(argp), [](const auto& flag ){return flag.c_str() ; } ); - if( m_cxx.find("clang") != std::string::npos ) + if( m_cxx.find("clang") != std::string::npos || m_cxx.find("llvm-g++") != std::string::npos) argp.push_back( "-Wno-return-type-c-linkage"); argp.push_back( fname.c_str() ); @@ -151,7 +155,7 @@ void CompilerWrapper::compileSource( const std::string& fname, const std::string if( childPID == 0 ) { execv( argp[0], const_cast( &argp[0] ) ); - perror( "execl()" ); + perror( "execv() in ../src/CompilerWrapper.cpp" ); // add "CompilerWrapper::Verbose true" to .opt file to diagnose exit( 0 ); } int status = 0; From d75272d6f85d4a7d47a4280387b65cbf15429f62 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 09:27:15 +0100 Subject: [PATCH 130/250] Improve file I/O for osx, and add error messages for invalid vertices in TreePhaseSpace --- AmpGen/Utilities.h | 1 + src/TreePhaseSpace.cpp | 4 ++++ src/Utilities.cpp | 8 +------- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/AmpGen/Utilities.h b/AmpGen/Utilities.h index 985bd3fdd71..b7792093558 100644 --- a/AmpGen/Utilities.h +++ b/AmpGen/Utilities.h @@ -116,6 +116,7 @@ namespace AmpGen { std::ifstream inFile( filename.c_str() ); while ( inFile.good() ) { std::getline( inFile, tmp ); + tmp.erase( std::remove_if( tmp.begin(), tmp.end(), [](const char c){ return c == '\r'; }), tmp.end() ); if ( tmp.size() == 0 || tmp[0] == ignoreLinesThatBeginWith ) continue; toDo( tmp ); } diff --git a/src/TreePhaseSpace.cpp b/src/TreePhaseSpace.cpp index 1f35c090575..b2b5de5e232 100644 --- a/src/TreePhaseSpace.cpp +++ b/src/TreePhaseSpace.cpp @@ -257,6 +257,10 @@ TreePhaseSpace::Vertex TreePhaseSpace::Vertex::make(const Particle& particle, Tr parent->setRhoMax(); return *parent; } + if( decayProducts.size() > 2 ) + { + ERROR("Decomposition only implemented for quasi two-body decays, vertex: " << particle << " does not result in valid phase space"); + } return TreePhaseSpace::Vertex(); } diff --git a/src/Utilities.cpp b/src/Utilities.cpp index 4b61ec20d22..c6f44b2ff53 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -17,13 +17,7 @@ std::vector AmpGen::vectorFromFile( const std::string& filename, const char ignoreLinesThatBeginWith ) { std::vector output; - std::string tmp; - std::ifstream inFile( filename.c_str() ); - while ( inFile.good() ) { - std::getline( inFile, tmp ); - if ( tmp.size() == 0 || tmp[0] == ignoreLinesThatBeginWith ) continue; - output.push_back( tmp ); - } + processFile( filename, [output](const std::string& line) mutable -> void {output.push_back(line);} ); return output; } From eb43c9803f198476bbc0bf8a3cfaa7ceb1ea4345 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 09:46:20 +0100 Subject: [PATCH 131/250] remove brew install commands from .travis.yml for osx --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fa5bbe03951..fe59dc2bcd4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,8 +40,6 @@ addons: - libtbb-dev before_install: -- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update ; fi -- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install graphviz; fi - source .ci/build_root.sh # Build your code e.g. by calling make From d0d45cd6d520b2fe0658cc837afc60b7a2d0ca79 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 10:19:34 +0100 Subject: [PATCH 132/250] still debugging osx travis configuration --- .ci/{build_root.sh => build_root_linux.sh} | 2 +- .ci/build_root_osx.sh | 1 + .travis.yml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) rename .ci/{build_root.sh => build_root_linux.sh} (89%) create mode 100644 .ci/build_root_osx.sh diff --git a/.ci/build_root.sh b/.ci/build_root_linux.sh similarity index 89% rename from .ci/build_root.sh rename to .ci/build_root_linux.sh index 7b71f79c418..edb24f830da 100644 --- a/.ci/build_root.sh +++ b/.ci/build_root_linux.sh @@ -1,5 +1,5 @@ -if [["$TRAVIS_OS_NAME" = "osx" ]] ; then return; fi +# if [["$TRAVIS_OS_NAME" = "osx" ]] ; then return; fi set -evx diff --git a/.ci/build_root_osx.sh b/.ci/build_root_osx.sh new file mode 100644 index 00000000000..8057280c3eb --- /dev/null +++ b/.ci/build_root_osx.sh @@ -0,0 +1 @@ +echo "Building ROOT for OSX..." diff --git a/.travis.yml b/.travis.yml index fe59dc2bcd4..979aae69d34 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,7 +40,7 @@ addons: - libtbb-dev before_install: -- source .ci/build_root.sh + - source .ci/build_root_${TRAVIS_OS_NAME}.sh # Build your code e.g. by calling make script: From a6c27510e08b9460c1cb7557bded9c81b0919c17 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 10:33:27 +0100 Subject: [PATCH 133/250] split travis job for osx/linus --- .ci/travis_linux.sh | 24 ++++++++++++++++++++++++ .ci/travis_osx.sh | 21 +++++++++++++++++++++ .travis.yml | 5 +++-- 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 .ci/travis_linux.sh create mode 100644 .ci/travis_osx.sh diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh new file mode 100644 index 00000000000..f72db1ad5ea --- /dev/null +++ b/.ci/travis_linux.sh @@ -0,0 +1,24 @@ +echo -en 'travis_fold:start:script.build\\r' +echo "Building..." +echo "Building under OS: $TRAVIS_OS_NAME" +set -evx + +mkdir -p build +cd build +cmake .. -DUSE_OPENMP=0 +cmake --build . -- -j2 + +set +evx + +cd .. + +./build/bin/Generator options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 1000 + + +# echo -e 'travis_fold:end:script.build\\r' +# echo -en 'travis_fold:start:script.test\\r' +# echo "Testing..." +# set -evx + +# ctest --output-on-failure + diff --git a/.ci/travis_osx.sh b/.ci/travis_osx.sh new file mode 100644 index 00000000000..4887a1d656d --- /dev/null +++ b/.ci/travis_osx.sh @@ -0,0 +1,21 @@ +echo -en 'travis_fold:start:script.build\\r' +echo "Building..." +echo "Building under OS: $TRAVIS_OS_NAME" +mkdir -p build +cd build +echo "CMake-ing" +cmake .. -DUSE_OPENMP=0 +echo "Building ..." +cmake --build . -- -j2 +cd .. +echo "Running test job ..." +./build/bin/Generator options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 1000 + + +# echo -e 'travis_fold:end:script.build\\r' +# echo -en 'travis_fold:start:script.test\\r' +# echo "Testing..." +# set -evx + +# ctest --output-on-failure + diff --git a/.travis.yml b/.travis.yml index 979aae69d34..8dab4d4a028 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,12 +40,13 @@ addons: - libtbb-dev before_install: + - chmod +x .ci/build_root_${TRAVIS_OS_NAME}.sh - source .ci/build_root_${TRAVIS_OS_NAME}.sh # Build your code e.g. by calling make script: - - chmod +x .ci/travis.sh - - source .ci/travis.sh + - chmod +x .ci/travis_${TRAVIS_OS_NAME}.sh + - source .ci/travis_${TRAVIS_OS_NAME}.sh # Generate and deploy documentation after_success: From 2a1801f0260430eb4808b9e0236d0ff0063d4325 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 10:42:57 +0100 Subject: [PATCH 134/250] add actual build root options for osx --- .ci/build_root_osx.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.ci/build_root_osx.sh b/.ci/build_root_osx.sh index 8057280c3eb..b7809a23942 100644 --- a/.ci/build_root_osx.sh +++ b/.ci/build_root_osx.sh @@ -1 +1,15 @@ -echo "Building ROOT for OSX..." +echo "Building ROOT for OSX [DIR=${DEPS_DIR}]" + +pushd $DEPS_DIR + +# root_v6.12.06.Linux-ubuntu16-x86_64-gcc5.4.tar.gz +ROOT_URL="https://root.cern.ch/download/root_v6.12.06.macosx64-10.12-clang90.tar.gz" + +if [ ! -f "${DEPS_DIR}/root/bin/root-config" ] ; then + echo "Downloading Root" + mkdir -p root + travis_retry wget --no-check-certificate --quiet -O - "${ROOT_URL}" | tar --strip-components=1 -xz -C root +fi + +source "${DEPS_DIR}/root/bin/thisroot.sh" +popd From 8a1ed0d6d9348cdfea90ec08e48dc4e20a7f4b5b Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 14:10:57 +0100 Subject: [PATCH 135/250] still fixing osx ci --- .ci/build_root_linux.sh | 6 ++---- .ci/travis_linux.sh | 2 +- .ci/travis_osx.sh | 4 ++-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.ci/build_root_linux.sh b/.ci/build_root_linux.sh index edb24f830da..66bca9f5a6b 100644 --- a/.ci/build_root_linux.sh +++ b/.ci/build_root_linux.sh @@ -3,8 +3,7 @@ set -evx -old_pwd=$PWD -cd $DEPS_DIR +pushd $DEPS_DIR # root_v6.12.06.Linux-ubuntu16-x86_64-gcc5.4.tar.gz ROOT_URL="https://root.cern.ch/download/root_v6.12.06.Linux-ubuntu16-x86_64-gcc5.4.tar.gz" @@ -16,7 +15,6 @@ if [[ ! -f "${DEPS_DIR}/root/bin/root-config" ]] ; then fi source "${DEPS_DIR}/root/bin/thisroot.sh" -# popd -cd $old_pwd +popd set +evx diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh index f72db1ad5ea..b7ad8a09d6e 100644 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -5,7 +5,7 @@ set -evx mkdir -p build cd build -cmake .. -DUSE_OPENMP=0 +cmake .. cmake --build . -- -j2 set +evx diff --git a/.ci/travis_osx.sh b/.ci/travis_osx.sh index 4887a1d656d..c91f6260d09 100644 --- a/.ci/travis_osx.sh +++ b/.ci/travis_osx.sh @@ -4,9 +4,9 @@ echo "Building under OS: $TRAVIS_OS_NAME" mkdir -p build cd build echo "CMake-ing" -cmake .. -DUSE_OPENMP=0 +cmake .. -DUSE_OPENMP=0 -DCMAKE_CXX_COMPILER=clang echo "Building ..." -cmake --build . -- -j2 +cmake --build . -- -j2 cd .. echo "Running test job ..." ./build/bin/Generator options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 1000 From 397ce7d23a4418811cb276ea3f388b44e8d5a22b Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 14:19:58 +0100 Subject: [PATCH 136/250] Update gcc -> gcc8 in .travis.yml --- .travis.yml | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8dab4d4a028..01ed567cbde 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,25 @@ sudo: false -os: - - linux - - osx - -# dist: xenial -compiler: - - gcc - - clang +# os: +# - linux +# - osx +# +# compiler: +# - gcc +# - clang +matrix: + include: + - os: osx + osx_image: xcode10.1 + compiler: clang + - os: linux + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-8 + env: + - MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" + cache: From b084063f707c4631c26e6d5f0db15d3b0586b2be Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 14:25:20 +0100 Subject: [PATCH 137/250] Update gcc -> gcc8 in .travis.yml --- .travis.yml | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 01ed567cbde..e35bb868abe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,11 +12,17 @@ matrix: osx_image: xcode10.1 compiler: clang - os: linux - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-8 + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-8 + - doxygen + - doxygen-doc + - doxygen-gui + - graphviz + - libtbb-dev env: - MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" @@ -42,16 +48,6 @@ env: - GH_REPO_REF: github.com/GooFit/AmpGen.git - DEPS_DIR: "${TRAVIS_BUILD_DIR}/deps" -# Install dependencies -addons: - apt: - packages: - - doxygen - - doxygen-doc - - doxygen-gui - - graphviz - - libtbb-dev - before_install: - chmod +x .ci/build_root_${TRAVIS_OS_NAME}.sh - source .ci/build_root_${TRAVIS_OS_NAME}.sh From 1a289811c2db43fca946ee1ed7738ef43600d9fb Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 14:30:48 +0100 Subject: [PATCH 138/250] set cxx compiler explicitly for travis build --- .ci/travis_linux.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh index b7ad8a09d6e..9f29206a32a 100644 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -1,11 +1,11 @@ echo -en 'travis_fold:start:script.build\\r' echo "Building..." -echo "Building under OS: $TRAVIS_OS_NAME" +echo "Building under OS: $TRAVIS_OS_NAME, CXX =$CXX" set -evx mkdir -p build cd build -cmake .. +cmake .. -DCMAKE_CXX_COMPILER=$CXX cmake --build . -- -j2 set +evx From 42599faebf6cf9beb88308ab675f173ef9e58847 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 14:35:56 +0100 Subject: [PATCH 139/250] set cxx compiler explicitly for travis build --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index e35bb868abe..cc1cf226a44 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,6 +49,7 @@ env: - DEPS_DIR: "${TRAVIS_BUILD_DIR}/deps" before_install: + - eval "${MATRIX_EVAL}" - chmod +x .ci/build_root_${TRAVIS_OS_NAME}.sh - source .ci/build_root_${TRAVIS_OS_NAME}.sh From 40afbba1dee539c8c45f95140f27ce7014f78e9c Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 14:47:37 +0100 Subject: [PATCH 140/250] update ROOT version in ci --- .ci/build_root_linux.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci/build_root_linux.sh b/.ci/build_root_linux.sh index 66bca9f5a6b..257093efd88 100644 --- a/.ci/build_root_linux.sh +++ b/.ci/build_root_linux.sh @@ -6,7 +6,8 @@ set -evx pushd $DEPS_DIR # root_v6.12.06.Linux-ubuntu16-x86_64-gcc5.4.tar.gz -ROOT_URL="https://root.cern.ch/download/root_v6.12.06.Linux-ubuntu16-x86_64-gcc5.4.tar.gz" +# ROOT_URL="https://root.cern.ch/download/root_v6.12.06.Linux-ubuntu16-x86_64-gcc5.4.tar.gz" +ROOT_URL="https://root.cern.ch/download/root_v6.13.08.Linux-fedora28-x86_64-gcc8.0.tar.gz" if [[ ! -f "${DEPS_DIR}/root/bin/root-config" ]] ; then echo "Downloading Root" From fc29d33f2842f7f9f08412473cbd3e7ac4b73b08 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 15:04:54 +0100 Subject: [PATCH 141/250] try to use conda for ROOT --- .ci/build_root_linux.sh | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/.ci/build_root_linux.sh b/.ci/build_root_linux.sh index 257093efd88..e8cc9a17feb 100644 --- a/.ci/build_root_linux.sh +++ b/.ci/build_root_linux.sh @@ -7,13 +7,20 @@ pushd $DEPS_DIR # root_v6.12.06.Linux-ubuntu16-x86_64-gcc5.4.tar.gz # ROOT_URL="https://root.cern.ch/download/root_v6.12.06.Linux-ubuntu16-x86_64-gcc5.4.tar.gz" -ROOT_URL="https://root.cern.ch/download/root_v6.13.08.Linux-fedora28-x86_64-gcc8.0.tar.gz" +# ROOT_URL="https://root.cern.ch/download/root_v6.13.08.Linux-fedora28-x86_64-gcc8.0.tar.gz" +# +# if [[ ! -f "${DEPS_DIR}/root/bin/root-config" ]] ; then +# echo "Downloading Root" +# mkdir -p root +# travis_retry wget --no-check-certificate --quiet -O - "${ROOT_URL}" | tar --strip-components=1 -xz -C root +# fi +wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh +bash miniconda.sh -b -p $HOME/miniconda +export PATH="$HOME/miniconda/bin:$PATH" +hash -r +conda config --add channels conda-forge +conda install -c conda-forge/label/gcc8 root -if [[ ! -f "${DEPS_DIR}/root/bin/root-config" ]] ; then - echo "Downloading Root" - mkdir -p root - travis_retry wget --no-check-certificate --quiet -O - "${ROOT_URL}" | tar --strip-components=1 -xz -C root -fi source "${DEPS_DIR}/root/bin/thisroot.sh" popd From 0b37c449cfc552237d9ff1077b986be856f76992 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 15:12:20 +0100 Subject: [PATCH 142/250] ahhhh --- .ci/build_root_linux.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.ci/build_root_linux.sh b/.ci/build_root_linux.sh index e8cc9a17feb..032676a8f88 100644 --- a/.ci/build_root_linux.sh +++ b/.ci/build_root_linux.sh @@ -19,8 +19,7 @@ bash miniconda.sh -b -p $HOME/miniconda export PATH="$HOME/miniconda/bin:$PATH" hash -r conda config --add channels conda-forge -conda install -c conda-forge/label/gcc8 root - +conda install --quiet --yes -c conda-forge/label/gcc8 root source "${DEPS_DIR}/root/bin/thisroot.sh" popd From 020ca6582a59a9b50a453d942815a244e9162b9e Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 15:34:03 +0100 Subject: [PATCH 143/250] fix miniconda --- .ci/build_root_linux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 .ci/build_root_linux.sh diff --git a/.ci/build_root_linux.sh b/.ci/build_root_linux.sh old mode 100644 new mode 100755 index 032676a8f88..4c39a2ba37a --- a/.ci/build_root_linux.sh +++ b/.ci/build_root_linux.sh @@ -21,7 +21,7 @@ hash -r conda config --add channels conda-forge conda install --quiet --yes -c conda-forge/label/gcc8 root -source "${DEPS_DIR}/root/bin/thisroot.sh" +source "$HOME/miniconda/bin/thisroot.sh" popd set +evx From c63717d6de867e413a6c4ed7c056e63dce867218 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 16:24:53 +0100 Subject: [PATCH 144/250] Try to use conda install of cxx --- .ci/build_root_linux.sh | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/.ci/build_root_linux.sh b/.ci/build_root_linux.sh index 4c39a2ba37a..21c76a1efc8 100755 --- a/.ci/build_root_linux.sh +++ b/.ci/build_root_linux.sh @@ -5,23 +5,15 @@ set -evx pushd $DEPS_DIR -# root_v6.12.06.Linux-ubuntu16-x86_64-gcc5.4.tar.gz -# ROOT_URL="https://root.cern.ch/download/root_v6.12.06.Linux-ubuntu16-x86_64-gcc5.4.tar.gz" -# ROOT_URL="https://root.cern.ch/download/root_v6.13.08.Linux-fedora28-x86_64-gcc8.0.tar.gz" -# -# if [[ ! -f "${DEPS_DIR}/root/bin/root-config" ]] ; then -# echo "Downloading Root" -# mkdir -p root -# travis_retry wget --no-check-certificate --quiet -O - "${ROOT_URL}" | tar --strip-components=1 -xz -C root -# fi wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh -bash miniconda.sh -b -p $HOME/miniconda -export PATH="$HOME/miniconda/bin:$PATH" +bash miniconda.sh -b -p $DEPS_DIR/miniconda +export PATH="$DEPS_DIR/miniconda/bin:$PATH" hash -r conda config --add channels conda-forge conda install --quiet --yes -c conda-forge/label/gcc8 root -source "$HOME/miniconda/bin/thisroot.sh" +source "$DEPS_DIR/miniconda/bin/thisroot.sh" +export CXX="$DEPS_DIR/miniconda/bin/g++" popd set +evx From a6dd2c3f75ea40d5bbdbc4085ad6b507ebc0ff75 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 16:34:37 +0100 Subject: [PATCH 145/250] fix for std::optional bug is osx --- src/Wigner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Wigner.cpp b/src/Wigner.cpp index 3159d43f5b5..ecbc091ddfe 100644 --- a/src/Wigner.cpp +++ b/src/Wigner.cpp @@ -262,7 +262,7 @@ Expression AmpGen::helicityAmplitude(const Particle& particle, else S = particle.S()/2.; auto recoupling_constants = calculate_recoupling_constants( particle.spin(), Mz, L, S, d1.spin(), d2.spin() ); auto mod = particle.attribute("helAmp"); - if( mod != stdx::nullopt ) recoupling_constants = userHelicityCouplings( mod.value() ); + if( mod != stdx::nullopt ) recoupling_constants = userHelicityCouplings( *mod ); if( recoupling_constants.size() == 0 ){ WARNING( particle.uniqueString() << " " << particle.spin() << " " << From 993cd27bee3748be9c8b2365d3c68db025387015 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 16:50:30 +0100 Subject: [PATCH 146/250] trying to fix AppleClang build ... --- Standalone.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Standalone.cmake b/Standalone.cmake index 96e84405fb5..e8b80debe79 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -65,6 +65,7 @@ target_include_directories(AmpGen SYSTEM PUBLIC "${ROOT_INCLUDE_DIRS}") target_link_libraries(AmpGen PUBLIC ${ROOT_LIBRARIES} ${CMAKE_DL_LIBS}) + if( ( NOT TARGET ROOT::Minuit2 AND NOT TARGET Minuit2 ) OR "${extern_minuit2}" ) message( STATUS "Use external Minuit2") add_subdirectory("extern/Minuit2") @@ -132,7 +133,10 @@ target_compile_options(AmpGen -march=native $<$:-Ofast>) -if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") +if("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" ) + target_link_libraries(AmpGen PUBLIC stdc++) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -lstdc++") +elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -lstdc++") else() target_compile_options(AmpGen PUBLIC -Wno-suggest-override) From d22efbfccb5f6118ac5b4501179febf140130542 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 17:12:34 +0100 Subject: [PATCH 147/250] Add pragma to fix libstdc++ problem on apple --- .ci/travis.sh | 24 ------------------------ .ci/travis_osx.sh | 2 +- .travis.yml | 7 ------- src/CompilerWrapper.cpp | 6 +++++- 4 files changed, 6 insertions(+), 33 deletions(-) delete mode 100644 .ci/travis.sh diff --git a/.ci/travis.sh b/.ci/travis.sh deleted file mode 100644 index f72db1ad5ea..00000000000 --- a/.ci/travis.sh +++ /dev/null @@ -1,24 +0,0 @@ -echo -en 'travis_fold:start:script.build\\r' -echo "Building..." -echo "Building under OS: $TRAVIS_OS_NAME" -set -evx - -mkdir -p build -cd build -cmake .. -DUSE_OPENMP=0 -cmake --build . -- -j2 - -set +evx - -cd .. - -./build/bin/Generator options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 1000 - - -# echo -e 'travis_fold:end:script.build\\r' -# echo -en 'travis_fold:start:script.test\\r' -# echo "Testing..." -# set -evx - -# ctest --output-on-failure - diff --git a/.ci/travis_osx.sh b/.ci/travis_osx.sh index c91f6260d09..e16964005cf 100644 --- a/.ci/travis_osx.sh +++ b/.ci/travis_osx.sh @@ -4,7 +4,7 @@ echo "Building under OS: $TRAVIS_OS_NAME" mkdir -p build cd build echo "CMake-ing" -cmake .. -DUSE_OPENMP=0 -DCMAKE_CXX_COMPILER=clang +cmake .. # -DUSE_OPENMP=0 -DCMAKE_CXX_COMPILER=clang echo "Building ..." cmake --build . -- -j2 cd .. diff --git a/.travis.yml b/.travis.yml index cc1cf226a44..3f1aa0de184 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,4 @@ sudo: false -# os: -# - linux -# - osx -# -# compiler: -# - gcc -# - clang matrix: include: - os: osx diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index ed0992f8ab3..83c1aaa9bec 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -133,8 +133,12 @@ void CompilerWrapper::compileSource( const std::string& fname, const std::string "-rdynamic", "-fPIC"}; std::transform( compile_flags.begin(), compile_flags.end(), std::back_inserter(argp), [](const auto& flag ){return flag.c_str() ; } ); - if( m_cxx.find("clang") != std::string::npos ) + if( m_cxx.find("clang") != std::string::npos ){ argp.push_back( "-Wno-return-type-c-linkage"); + #if __APPLE__ + argp.push_back("-lstdc++"); + #endif + } argp.push_back( fname.c_str() ); argp.push_back( "-o"); From d5d7402f8a768fefdfc409760b5b3f51a923c360 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 17:21:25 +0100 Subject: [PATCH 148/250] explicitly select clang for apple build --- .ci/travis_osx.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/travis_osx.sh b/.ci/travis_osx.sh index e16964005cf..3804d03e241 100644 --- a/.ci/travis_osx.sh +++ b/.ci/travis_osx.sh @@ -4,7 +4,7 @@ echo "Building under OS: $TRAVIS_OS_NAME" mkdir -p build cd build echo "CMake-ing" -cmake .. # -DUSE_OPENMP=0 -DCMAKE_CXX_COMPILER=clang +cmake .. -DCMAKE_CXX_COMPILER=clang echo "Building ..." cmake --build . -- -j2 cd .. From 11f7960defcfc70b48c68b0d6a81d1f31b4a0a4f Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Feb 2020 17:45:22 +0100 Subject: [PATCH 149/250] Update CompilerWrapper.cpp fix bug introduced when merging with master --- src/CompilerWrapper.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index 42a1a6cdd96..0b63f0d3d44 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -137,7 +137,8 @@ void CompilerWrapper::compileSource( const std::string& fname, const std::string "-rdynamic", "-fPIC"}; std::transform( compile_flags.begin(), compile_flags.end(), std::back_inserter(argp), [](const auto& flag ){return flag.c_str() ; } ); - if( m_cxx.find("clang") != std::string::npos || m_cxx.find("llvm-g++") != std::string::npos) + if( m_cxx.find("clang") != std::string::npos || m_cxx.find("llvm-g++") != std::string::npos) + { argp.push_back( "-Wno-return-type-c-linkage"); #if __APPLE__ argp.push_back("-lstdc++"); From 9088457b2b3cdd3e194a91c8ec9ff9a62ccfdccc Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 6 Feb 2020 11:06:00 +0100 Subject: [PATCH 150/250] Fix vectorFromFile that was broken by last commit --- src/Utilities.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utilities.cpp b/src/Utilities.cpp index c6f44b2ff53..e0c04a9ce94 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -17,7 +17,7 @@ std::vector AmpGen::vectorFromFile( const std::string& filename, const char ignoreLinesThatBeginWith ) { std::vector output; - processFile( filename, [output](const std::string& line) mutable -> void {output.push_back(line);} ); + processFile( filename, [&output](const std::string& line) mutable -> void {output.push_back(line);} ); return output; } From 5f9272aa692ad931ed85d9f4cc9473f26f1ab573 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 6 Feb 2020 22:36:31 +0100 Subject: [PATCH 151/250] Add OpenMP using conda to the osx build --- .ci/build_root_linux.sh | 7 ------- .ci/build_root_osx.sh | 19 ++++++++----------- CMakeLists.txt | 2 +- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/.ci/build_root_linux.sh b/.ci/build_root_linux.sh index 21c76a1efc8..fd12bdea9b6 100755 --- a/.ci/build_root_linux.sh +++ b/.ci/build_root_linux.sh @@ -1,8 +1,3 @@ - -# if [["$TRAVIS_OS_NAME" = "osx" ]] ; then return; fi - -set -evx - pushd $DEPS_DIR wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh @@ -15,5 +10,3 @@ conda install --quiet --yes -c conda-forge/label/gcc8 root source "$DEPS_DIR/miniconda/bin/thisroot.sh" export CXX="$DEPS_DIR/miniconda/bin/g++" popd - -set +evx diff --git a/.ci/build_root_osx.sh b/.ci/build_root_osx.sh index b7809a23942..92c8a459a2f 100644 --- a/.ci/build_root_osx.sh +++ b/.ci/build_root_osx.sh @@ -1,15 +1,12 @@ -echo "Building ROOT for OSX [DIR=${DEPS_DIR}]" - pushd $DEPS_DIR -# root_v6.12.06.Linux-ubuntu16-x86_64-gcc5.4.tar.gz -ROOT_URL="https://root.cern.ch/download/root_v6.12.06.macosx64-10.12-clang90.tar.gz" - -if [ ! -f "${DEPS_DIR}/root/bin/root-config" ] ; then - echo "Downloading Root" - mkdir -p root - travis_retry wget --no-check-certificate --quiet -O - "${ROOT_URL}" | tar --strip-components=1 -xz -C root -fi +wget -nv https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh -O ~/miniconda.sh +bash ~/miniconda.sh -b -p $DEPS_DIR/miniconda +export PATH="$DEPS_DIR/miniconda/bin:$PATH" +hash -r +conda config --add channels conda-forge +conda install --quiet --yes -c openmp root -source "${DEPS_DIR}/root/bin/thisroot.sh" +source "$DEPS_DIR/miniconda/bin/thisroot.sh" popd + diff --git a/CMakeLists.txt b/CMakeLists.txt index 8cf6ef67852..91f484b9100 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ if(COMMAND gaudi_subdir) LINK_LIBRARIES AmpGen) endforeach() else() - cmake_minimum_required(VERSION 3.3) + cmake_minimum_required(VERSION 3.12) project(AmpGen LANGUAGES CXX VERSION 1.2) include(Standalone.cmake) endif() From b701de1aafe6dc1105f18f898620eae6f7b8b60f Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 6 Feb 2020 22:41:25 +0100 Subject: [PATCH 152/250] Add OpenMP using conda to the osx build --- .ci/build_root_osx.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/build_root_osx.sh b/.ci/build_root_osx.sh index 92c8a459a2f..c1388ec8472 100644 --- a/.ci/build_root_osx.sh +++ b/.ci/build_root_osx.sh @@ -5,7 +5,7 @@ bash ~/miniconda.sh -b -p $DEPS_DIR/miniconda export PATH="$DEPS_DIR/miniconda/bin:$PATH" hash -r conda config --add channels conda-forge -conda install --quiet --yes -c openmp root +conda install --quiet --yes -c conda-forge root openmp source "$DEPS_DIR/miniconda/bin/thisroot.sh" popd From a2805fa32e7cf90e9255685301333fda0961b766 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 6 Feb 2020 23:09:51 +0100 Subject: [PATCH 153/250] still trying to add openmp to osx ci.. --- .ci/build_root_osx.sh | 3 +-- .travis.yml | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.ci/build_root_osx.sh b/.ci/build_root_osx.sh index c1388ec8472..e457e1659ce 100644 --- a/.ci/build_root_osx.sh +++ b/.ci/build_root_osx.sh @@ -5,8 +5,7 @@ bash ~/miniconda.sh -b -p $DEPS_DIR/miniconda export PATH="$DEPS_DIR/miniconda/bin:$PATH" hash -r conda config --add channels conda-forge -conda install --quiet --yes -c conda-forge root openmp - +conda install --quiet --yes -c conda-forge root source "$DEPS_DIR/miniconda/bin/thisroot.sh" popd diff --git a/.travis.yml b/.travis.yml index 3f1aa0de184..c5d0fe25a6e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,9 @@ matrix: - os: osx osx_image: xcode10.1 compiler: clang + addons: + homebrew: + casks: clang-omp - os: linux addons: apt: From 460c7cca4c41f520692c5716b2ac3ef74d711a6a Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 6 Feb 2020 23:15:21 +0100 Subject: [PATCH 154/250] still trying to add openmp to osx ci.. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c5d0fe25a6e..8b9075ca843 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,8 @@ matrix: compiler: clang addons: homebrew: - casks: clang-omp + packages: + - clang-omp - os: linux addons: apt: From 03709dc86ec94a714c365d013c4e01a6951d1c74 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 6 Feb 2020 23:21:14 +0100 Subject: [PATCH 155/250] still trying to add openmp to osx ci.. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8b9075ca843..801d59f7faa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,8 @@ matrix: addons: homebrew: packages: - - clang-omp + - libomp + - llvm - os: linux addons: apt: From 050d6479736f5fe82c042fec6e50511567f382fd Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 7 Feb 2020 08:41:37 +0100 Subject: [PATCH 156/250] fixing osx ci --- .travis.yml | 1 - Standalone.cmake | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 801d59f7faa..792c790b0ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,6 @@ matrix: homebrew: packages: - libomp - - llvm - os: linux addons: apt: diff --git a/Standalone.cmake b/Standalone.cmake index e8b80debe79..6bb67d5459f 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -137,6 +137,7 @@ if("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" ) target_link_libraries(AmpGen PUBLIC stdc++) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -lstdc++") elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + target_link_libraries(AmpGen PUBLIC stdc++) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -lstdc++") else() target_compile_options(AmpGen PUBLIC -Wno-suggest-override) From c3a581d68b86d553a41c8a30f8ad436cc238664f Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 7 Feb 2020 08:58:57 +0100 Subject: [PATCH 157/250] Explicitly link applications against ROOT libraries --- .travis.yml | 3 ++- Standalone.cmake | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 792c790b0ec..8dbf58565e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ -sudo: false +language: cpp + matrix: include: - os: osx diff --git a/Standalone.cmake b/Standalone.cmake index 6bb67d5459f..02fdb25329e 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -151,7 +151,7 @@ foreach( file ${applications} ) # cmake_print_variables(Executable) add_executable(${Executable} ${file}) target_compile_options(${Executable} PUBLIC -g3 -Ofast) - target_link_libraries(${Executable} PUBLIC AmpGen) + target_link_libraries(${Executable} PUBLIC AmpGen ${ROOT_LIBRARIES}) endforeach() foreach( file ${examples} ) From 6c9b7d2909c60261a8cc739edeef61b4c942c772 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 7 Feb 2020 09:20:52 +0100 Subject: [PATCH 158/250] still fix osx ci --- .ci/build_root_osx.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.ci/build_root_osx.sh b/.ci/build_root_osx.sh index e457e1659ce..33d47b5f33f 100644 --- a/.ci/build_root_osx.sh +++ b/.ci/build_root_osx.sh @@ -6,6 +6,12 @@ export PATH="$DEPS_DIR/miniconda/bin:$PATH" hash -r conda config --add channels conda-forge conda install --quiet --yes -c conda-forge root -source "$DEPS_DIR/miniconda/bin/thisroot.sh" +. $DEPS_DIR/miniconda/etc/profile.d/conda.sh +conda activate root +# . "/home/tim/miniconda/etc/profile.d/conda.sh" +# else +# export PATH="/home/tim/miniconda/bin:$PATH" + +# source "$DEPS_DIR/miniconda/bin/thisroot.sh" popd From b4ca3c340b00c638deb67dd70dfd13914a0f3b8e Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 7 Feb 2020 09:46:11 +0100 Subject: [PATCH 159/250] Remove CXX use as global variable for c++ compiler --- .ci/travis_osx.sh | 5 ++++- src/CompilerWrapper.cpp | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.ci/travis_osx.sh b/.ci/travis_osx.sh index 3804d03e241..d028657a802 100644 --- a/.ci/travis_osx.sh +++ b/.ci/travis_osx.sh @@ -1,9 +1,12 @@ echo -en 'travis_fold:start:script.build\\r' echo "Building..." echo "Building under OS: $TRAVIS_OS_NAME" + + + mkdir -p build cd build -echo "CMake-ing" +echo "CMake-ing, CXX = $CXX" cmake .. -DCMAKE_CXX_COMPILER=clang echo "Building ..." cmake --build . -- -j2 diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index 0b63f0d3d44..2a2699c7aa1 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -29,16 +29,16 @@ using namespace AmpGen; CompilerWrapper::CompilerWrapper( const bool& verbose ) : m_verbose(verbose), - m_cxx(getenv("CXX") != nullptr ? std::string( getenv( "CXX" ) ) : "") + m_cxx(getenv("AMPGEN_CXX") != nullptr ? std::string( getenv( "AMPGEN_CXX" ) ) : "") { if ( m_cxx == "" ) { #ifdef AMPGEN_CXX if( m_verbose ) - INFO( "Global variable CXX is undefined, using compiler variable AMPGEN_CXX: " << AMPGEN_CXX ); + INFO( "Global variable AMPGEN_CXX is undefined, using compiler variable AMPGEN_CXX: " << AMPGEN_CXX ); m_cxx = AMPGEN_CXX; #else m_cxx = getenv("AMPGEN_CXX") != nullptr ? std::string( getenv( "AMPGEN_CXX" ) ) : ""; - if( m_cxx == "" ) ERROR( "No configured compiler; set global variable CXX" ); + if( m_cxx == "" ) ERROR( "No configured compiler; set global variable AMPGEN_CXX" ); #endif } else { From e01cef7fa3585421441c3657af6bb659fc4d4987 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 27 Feb 2020 09:14:26 +0100 Subject: [PATCH 160/250] Add RapidSim as an optional external packages, fixes to unit tests --- .ci/travis_osx.sh | 2 -- AmpGen/AmplitudeRules.h | 39 +++++++++++++++++++++++++++++++ AmpGen/CompiledExpression.h | 38 ++++++++++++++---------------- AmpGen/CompiledExpressionBase.h | 6 +++-- AmpGen/FitResult.h | 6 ++--- AmpGen/MinuitParameterSet.h | 5 ++-- AmpGen/Tensor.h | 2 +- AmpGen/Utilities.h | 29 +++++++++++------------ Standalone.cmake | 19 +++++++++++++++ examples/SignalOnlyFitter.cpp | 2 +- src/AmplitudeRules.cpp | 2 +- src/CompiledExpressionBase.cpp | 26 ++++++++++++++++++++- src/FitResult.cpp | 11 ++++----- src/Lineshapes/CoupledChannel.cpp | 9 ++++--- src/MinuitParameterSet.cpp | 24 ++++++++----------- test/CMakeLists.txt | 7 ++---- test/test_AmplitudeRules.cpp | 33 +++++++++++++++++--------- test/test_ExpressionParser.cpp | 2 +- 18 files changed, 174 insertions(+), 88 deletions(-) diff --git a/.ci/travis_osx.sh b/.ci/travis_osx.sh index d028657a802..18d123b85ee 100644 --- a/.ci/travis_osx.sh +++ b/.ci/travis_osx.sh @@ -2,8 +2,6 @@ echo -en 'travis_fold:start:script.build\\r' echo "Building..." echo "Building under OS: $TRAVIS_OS_NAME" - - mkdir -p build cd build echo "CMake-ing, CXX = $CXX" diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index 71436e4bda3..e3a18d0f6c1 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -142,7 +142,46 @@ namespace AmpGen } return rt; } + + template <> struct TransitionMatrix + { + TransitionMatrix() = default; + TransitionMatrix(const Particle& dt, + const TotalCoupling& coupling, + const CompiledExpression & amp) : + decayTree(dt), + coupling(coupling), + amp(amp) {} + TransitionMatrix(const Particle& dt, + const TotalCoupling& coupling, + const MinuitParameterSet& mps, + const std::map& evtFormat, + const bool& debugThis=false) : + decayTree(dt), + coupling(coupling), + amp(decayTree.getExpression(debugThis ? &db : nullptr ), decayTree.decayDescriptor(), evtFormat, db, &mps ) { amp.use_rto();} + + const std::vector operator()(const Event& event) const { + std::vector rt; + amp(rt.data(), amp.externBuffer().data(), event.address() ); + return rt; + } + const std::vector operator()(const Event& event, const size_t& cacheOffset) const { + std::vector rt; + amp(rt.data(), amp.externBuffer().data(), event.address() + cacheOffset); + return rt; + } + const std::string decayDescriptor() const { return decayTree.decayDescriptor() ; } + + Particle decayTree; + TotalCoupling coupling; + complex_t coefficient; + DebugSymbols db; + CompiledExpression amp; + size_t addressData = {999}; + }; + } // namespace AmpGen #endif diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index 43d18aae373..8fe90dce51a 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -21,6 +21,10 @@ namespace AmpGen usually this is a std::complex, but in principal support also exists for computing coupled channel propagators (i.e. returning array types) */ + namespace detail { + template struct size_of { unsigned operator()(){ return sizeof(T); } }; + template <> struct size_of { unsigned operator()(){ return 0; } }; + } template class CompiledExpression : public CompiledExpressionBase @@ -50,14 +54,7 @@ namespace AmpGen std::string returnTypename() const override { return typeof(); } std::string fcnSignature() const override { - std::string signature; - auto argTypes = typelist(); - for( unsigned int i = 0 ; i < argTypes.size(); ++i ) - { - signature += argTypes[i] + " x"+std::to_string(i) ; - if( i != argTypes.size() - 1 ) signature += ", "; - } - return signature; + return CompiledExpressionBase::fcnSignature(typelist(), m_rto); } std::string args() const override { @@ -119,25 +116,16 @@ namespace AmpGen void compileWithParameters( std::ostream& stream ) const { DEBUG( "Compiling " << name() << " = " << hash() ); - // Avoid a warning about std::complex not being C compatible (it is) - // stream << "#pragma clang diagnostic push\n" - // << "#pragma clang diagnostic ignored \"-Wreturn-type-c-linkage\"\n"; stream << "extern \"C\" " << returnTypename() << " " << progName() << "_wParams" << "( const double*__restrict__ E ){" << std::endl; - stream << " double externalParameters [] = {"; - if ( m_externals.size() != 0 ) { - for ( unsigned int i = 0; i < m_externals.size() - 1; ++i ) { - stream << m_externals[i] << ", " ; - } - stream << m_externals[m_externals.size() - 1] << " }; " << std::endl; - } else stream << "0};" << std::endl; + stream << " double externalParameters [] = {" << (m_externals.size() == 0 ? "0" : vectorToString(m_externals,", ") ) <<"};\n" ; stream << " return " << progName() << "( externalParameters, E ); // E is P \n}\n"; - // stream << "#pragma clang diagnostic pop\n\n" << std::endl; } bool isReady() const override { return m_fcn.isLinked(); } bool isLinked() const { return m_fcn.isLinked() ; } - size_t returnTypeSize() const override { return sizeof( RETURN_TYPE ); } + + unsigned returnTypeSize() const override { return detail::size_of()(); } template < class T > RETURN_TYPE operator()( const T* event ) const @@ -199,6 +187,16 @@ namespace AmpGen return true; } }; + template + CompiledExpression + make_rto_expression( const Expression& expression, const std::string& name , const bool& verbose=false) + { + CompiledExpression rt(expression,name); + rt.use_rto(); + rt.compile(); + rt.prepare(); + return rt; + } template CompiledExpression diff --git a/AmpGen/CompiledExpressionBase.h b/AmpGen/CompiledExpressionBase.h index 97e7c245b73..6643d47d97f 100644 --- a/AmpGen/CompiledExpressionBase.h +++ b/AmpGen/CompiledExpressionBase.h @@ -55,7 +55,9 @@ namespace AmpGen virtual std::string args() const = 0; virtual void print() const = 0; virtual ~CompiledExpressionBase(); - virtual size_t returnTypeSize() const = 0; + virtual unsigned returnTypeSize() const = 0; + static std::string fcnSignature(const std::vector& argList, bool rto); + void use_rto(){ m_rto = true; } protected: Expression m_obj; std::string m_name; @@ -66,7 +68,7 @@ namespace AmpGen std::vector> m_debugSubexpressions; std::vector> m_cacheTransfers; std::shared_ptr m_resolver; - + bool m_rto = {false}; private: void addDebug( std::ostream& stream ) const; void addDependentExpressions( std::ostream& stream, size_t& sizeOfStream ) const; diff --git a/AmpGen/FitResult.h b/AmpGen/FitResult.h index 88cac144df5..01c09fd83e2 100644 --- a/AmpGen/FitResult.h +++ b/AmpGen/FitResult.h @@ -19,7 +19,7 @@ namespace AmpGen explicit FitResult( const FitResult& other ); explicit FitResult( const std::string& filename ); explicit FitResult( const Minimiser& mini ); - FitResult( const MinuitParameterSet& mps, const TMatrixD& covMini ); + FitResult( MinuitParameterSet& mps, const TMatrixD& covMini ); void addObservable( const std::string& name, const double& F ); void addChi2( const double& chi2, const double& nBins ); @@ -43,7 +43,7 @@ namespace AmpGen int nBins() const; std::map observables() const; - std::shared_ptr mps() const; + MinuitParameterSet* mps() const; std::vector fitFractions() const; std::vector parameters() const; @@ -56,7 +56,7 @@ namespace AmpGen LinearErrorPropagator getErrorPropagator( const bool& extended = false ) const; private: - std::shared_ptr m_mps; + MinuitParameterSet* m_mps; double m_chi2 = {0}; double m_LL = {-999}; double m_nBins = {0}; diff --git a/AmpGen/MinuitParameterSet.h b/AmpGen/MinuitParameterSet.h index 149d4f1aef8..13b79a00caf 100644 --- a/AmpGen/MinuitParameterSet.h +++ b/AmpGen/MinuitParameterSet.h @@ -22,10 +22,11 @@ namespace AmpGen MinuitParameterSet(); explicit MinuitParameterSet(const std::vector& params ); - MinuitParameterSet( const MinuitParameterSet& other ); + + MinuitParameterSet( const MinuitParameterSet& other ) = delete; ~MinuitParameterSet(); // = default; - MinuitParameterSet getFloating(); + // MinuitParameterSet getFloating(); bool add( MinuitParameter* parPtr ); MinuitParameter* add(const std::string& name, const Flag& flag, const double& mean, const double& sigma, const double& min = 0, const double& max = 0 ); diff --git a/AmpGen/Tensor.h b/AmpGen/Tensor.h index c0b656edcc8..d5a13ca827a 100644 --- a/AmpGen/Tensor.h +++ b/AmpGen/Tensor.h @@ -172,7 +172,7 @@ namespace AmpGen void resolve( ASTResolver& resolver ) const override; complex_t operator()() const override; operator Expression() const; - + Tensor tensor() const { return m_tensor;} private: Tensor m_tensor; }; diff --git a/AmpGen/Utilities.h b/AmpGen/Utilities.h index b7792093558..b321773df16 100644 --- a/AmpGen/Utilities.h +++ b/AmpGen/Utilities.h @@ -18,27 +18,26 @@ #include "AmpGen/MsgService.h" #include "AmpGen/MetaUtils.h" + + namespace AmpGen { - template - std::string vectorToString( const std::vector& obj, const std::string& delim = "" ) + template + std::string vectorToString( it_type begin, + it_type end, + const std::string& delim, + F fcn ) { std::stringstream ss; - if( obj.size() == 0 ) return ""; - for ( unsigned int i = 0 ; i < obj.size()-1; ++i ) - ss << obj[i] << delim; - ss << obj[obj.size()-1]; + if( begin == end ) return ""; + for ( auto it = begin; it != end-1; ++it) + ss << fcn(*it) << delim; + ss << fcn(*(end-1)); return ss.str(); } - - template - std::string vectorToString( const std::vector& obj, const std::string& delim="", const F& functor =[](const T& f){ return f ; } ) + template > + std::string vectorToString( const std::vector& obj, const std::string& delim = "", F f = [](const T& arg){ return arg; }) { - std::stringstream ss; - if( obj.size() == 0 ) return ""; - for ( unsigned int i = 0 ; i < obj.size()-1; ++i ) - ss << functor(obj[i]) << delim; - ss << functor(obj[obj.size()-1]); - return ss.str(); + return vectorToString( std::begin(obj), std::end(obj), delim, f); } template std::vector> nCr( const T& n, const T& r ) diff --git a/Standalone.cmake b/Standalone.cmake index 02fdb25329e..f96ab83bb78 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -103,6 +103,23 @@ if( USE_OPENMP ) endif() endif() +set(RAPIDSIM_DATA "") + +if( "${USE_RAPIDSIM}" ) + include(${CMAKE_ROOT}/Modules/FetchContent.cmake) + FetchContent_Declare( RapidSim GIT_REPOSITORY https://github.com/gcowan/RapidSim/ ) + if(NOT RapidSim_POPULATED) + message("Fetching RapidSim from: https://github.com/gcowan/RapidSim/") + FetchContent_Populate(RapidSim) + endif() + FetchContent_GetProperties(RapidSim) + set(RAPIDSIM_DATA "${CMAKE_BINARY_DIR}/_deps/rapidsim-src/rootfiles/" ) +endif() + +if( RAPIDSIM_DATA ) + message("Set RAPIDSIM_DATA = ${RAPIDSIM_DATA}") +endif() + # Default to XROOTD only if on CMT system. Can be overridden with -DAMPGEN_XROOTD=ON if(DEFINED ENV{CMTCONFIG}) set(AMPGEN_XROOTD_DEFAULT ON) @@ -169,6 +186,8 @@ foreach(file ${options_files}) execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${file}" "${CMAKE_BINARY_DIR}/bin/${OptionFile}") endforeach() +enable_testing() +set(Boost_NO_BOOST_CMAKE ON) add_subdirectory(test) include(CMakePackageConfigHelpers) diff --git a/examples/SignalOnlyFitter.cpp b/examples/SignalOnlyFitter.cpp index b3f1e0363e2..e49d43f317b 100644 --- a/examples/SignalOnlyFitter.cpp +++ b/examples/SignalOnlyFitter.cpp @@ -103,7 +103,7 @@ int main( int argc, char* argv[] ) /* Generate events to normalise the PDF with. This can also be loaded from a file, which will be the case when efficiency variations are included. Default number of normalisation events is 5 million. */ - EventList eventsMC = intFile == "" ? Generator<>(evtType, &rndm).generate(2e6) : EventList(intFile, evtType, GetGenPdf(true)); + EventList eventsMC = intFile == "" ? Generator<>(evtType, &rndm).generate(1e7) : EventList(intFile, evtType, GetGenPdf(true)); sig.setMC( eventsMC ); diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index 0a14362c65f..01e1c2737e6 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -94,7 +94,7 @@ std::vector AmplitudeRules::rulesForDecay(const std::string& head, con if(!hasDecay(head)) return std::vector(); if( prefix == "" )return m_rules[head]; std::vector rt = m_rules[head]; - rt.erase( std::remove_if( std::begin(rt), std::end(rt), [&prefix](auto& p){ return p.prefix() != prefix; } ) ); + rt.erase( std::remove_if( std::begin(rt), std::end(rt), [&prefix](auto& p){ return p.prefix() != prefix; } ), rt.end() ); return rt; } diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index 3233a917806..eb680b55b17 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -12,6 +12,7 @@ #include "AmpGen/CompilerWrapper.h" #include "AmpGen/ASTResolver.h" #include "AmpGen/ProfileClock.h" +#include "AmpGen/Tensor.h" using namespace AmpGen; CompiledExpressionBase::CompiledExpressionBase() = default; @@ -86,7 +87,22 @@ void CompiledExpressionBase::to_stream( std::ostream& stream ) const stream << "extern \"C\" const char* " << progName() << "_name() { return \"" << m_name << "\"; } \n"; bool enable_cuda = NamedParameter("UseCUDA",false); size_t sizeOfStream = 0; - if( !enable_cuda ){ + if( m_rto ) + { + stream << "extern \"C\" " << returnTypename() << " " << progName() << "(" << fcnSignature() << "){\n"; + addDependentExpressions( stream , sizeOfStream ); + if( is(m_obj) == false ){ + stream << "*r = " << m_obj.to_string(m_resolver.get()) << ";\n"; + stream << "}\n"; + } + else { + auto as_tensor = cast(m_obj).tensor(); + for(unsigned j=0; j != as_tensor.size(); ++j ) + stream << "r["<& argList, bool rto=false) +{ + unsigned counter=0; + auto fcn = [counter](const auto& str) mutable {return str + " x"+std::to_string(counter++); }; + if( rto ) return argList[0] + " r, " + vectorToString( argList.begin()+1, argList.end(), ", ", fcn ); + return vectorToString( argList.begin(), argList.end(), ", ", fcn); +} diff --git a/src/FitResult.cpp b/src/FitResult.cpp index 089d451876a..1e30bed851e 100644 --- a/src/FitResult.cpp +++ b/src/FitResult.cpp @@ -26,7 +26,7 @@ using namespace AmpGen; FitResult::FitResult() = default; FitResult::FitResult( const FitResult& other ) - : m_mps( std::make_shared( *other.mps() ) ) + : m_mps( other.mps() ) , m_chi2( other.chi2() ) , m_LL( other.LL() ) , m_nBins( other.nBins() ) @@ -39,13 +39,13 @@ FitResult::FitResult( const FitResult& other ) } FitResult::FitResult( const std::string& filename ) : - m_mps( std::make_shared() ) + m_mps( new MinuitParameterSet() ) { m_fitted = readFile( filename ); } FitResult::FitResult( const Minimiser& mini ) - : m_mps ( std::make_shared( *mini.parSet() ) ) + : m_mps ( mini.parSet() ) , m_LL ( mini.FCN() ) , m_nParam( 0 ) , m_status( mini.status() ) @@ -56,8 +56,7 @@ FitResult::FitResult( const Minimiser& mini ) } } -FitResult::FitResult( const MinuitParameterSet& mps, const TMatrixD& covMini ) : - m_mps( std::make_shared( mps ) ) +FitResult::FitResult( MinuitParameterSet& mps, const TMatrixD& covMini ) : m_mps(&mps) { if ( int( mps.size() ) != covMini.GetNcols() ) { ERROR( "Minuit parameter set size does not match covariance matrix size!" ); @@ -210,7 +209,7 @@ int FitResult::nParam() const { return m_nParam; } int FitResult::nBins() const { return m_nBins; } std::map FitResult::observables() const { return m_observables; } -std::shared_ptr FitResult::mps() const { return m_mps; } +MinuitParameterSet* FitResult::mps() const { return m_mps; } double FitResult::dof() const { return m_nBins - m_nParam - 1; } std::vector FitResult::fitFractions() const { return m_fitFractions; } diff --git a/src/Lineshapes/CoupledChannel.cpp b/src/Lineshapes/CoupledChannel.cpp index 8ef1ea6a2cc..8f8d149e159 100644 --- a/src/Lineshapes/CoupledChannel.cpp +++ b/src/Lineshapes/CoupledChannel.cpp @@ -75,11 +75,11 @@ Expression AmpGen::phaseSpace(const Expression& s, const Particle& p, const size const Expression radius = Parameter(p.name() + "_radius", p.props()->radius()); return rho_twoBody(s, s1, s2) * BlattWeisskopf(k2p*radius*radius, l); } - if( phsp_parameterisation == std::string("arXiv.0707.3596") ){ + else if( phsp_parameterisation == std::string("arXiv.0707.3596") ){ INFO("Got AS parametrisation"); return 2 * complex_sqrt(k2/s); } - if( phsp_parameterisation == std::string("CM") ) + else if( phsp_parameterisation == std::string("CM") ) { if( l != 0 ){ WARNING("Chew-Mandelstam only implemented for l=0"); @@ -94,6 +94,9 @@ Expression AmpGen::phaseSpace(const Expression& s, const Particle& p, const size auto arg = (s1 + s2 - s + 2*fcn::sqrt(s) * q )/ (2*m1*m2); return (2.*q * fcn::log(arg) / fcn::sqrt(s) - (s1-s2)*( 1./s - 1./sT ) * fcn::log(m1/m2) ) / ( 16.i * M_PI * M_PI ); } + else { + FATAL("Parametrisation: " << *phsp_parameterisation << " not found"); + } } if( fs.size() == 3 && ! p.daughter(0)->isStable() ) return rho_threeBody( s, *p.daughter(0), *p.daughter(1) ); if( fs.size() == 3 && ! p.daughter(1)->isStable() ) return rho_threeBody( s, *p.daughter(1), *p.daughter(0) ); @@ -114,7 +117,7 @@ DEFINE_LINESHAPE( CoupledChannel ) ADD_DEBUG( s , dbexpressions ); for( size_t i = 0 ; i < channels.size(); i+=2 ){ Particle p( channels[i] ); - DEBUG( "Adding channel ... " << p.uniqueString() << " coupling = " << NamedParameter( channels[i+1] ) ); + INFO( "Adding channel ... " << p.uniqueString() << " coupling = " << NamedParameter( channels[i+1] ) ); Expression coupling = Parameter(channels[i+1], 0); totalWidth = totalWidth + coupling * phaseSpace(s , p, p.L()); totalWidthAtPole = totalWidthAtPole + coupling * phaseSpace(mass*mass, p, p.L()); diff --git a/src/MinuitParameterSet.cpp b/src/MinuitParameterSet.cpp index c2a08ae0905..1bf0031846b 100644 --- a/src/MinuitParameterSet.cpp +++ b/src/MinuitParameterSet.cpp @@ -26,18 +26,15 @@ MinuitParameterSet::MinuitParameterSet(const std::vector& para for( auto& param : params ) add(param); } -MinuitParameterSet::MinuitParameterSet( const MinuitParameterSet& other ) - : m_parameters( other.m_parameters ), m_keyAccess( other.m_keyAccess ){} - -MinuitParameterSet MinuitParameterSet::getFloating() -{ - MinuitParameterSet floating; - for ( auto& param : *this ) { - if ( param->isFree() && dynamic_cast(param) != nullptr ) - floating.add(param); - } - return floating; -} +// MinuitParameterSet MinuitParameterSet::getFloating() +// { +// MinuitParameterSet floating; +// for ( auto& param : *this ) { +// if ( param->isFree() && dynamic_cast(param) != nullptr ) +// floating.add(param); +// } +// return floating; +// } bool MinuitParameterSet::addToEnd( MinuitParameter* parPtr ) { @@ -251,6 +248,5 @@ double MinuitParameterSet::operator()( const std::string& name ) MinuitParameterSet::~MinuitParameterSet() { - for( auto& param : m_parameters ) delete param; - + for( auto& param : m_parameters ) if( param != nullptr ) delete param; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2d2b93dba9d..9cd5d33cf5a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,11 +1,8 @@ - -enable_testing() -set(Boost_NO_BOOST_CMAKE ON) - find_package(Boost 1.67.0 COMPONENTS unit_test_framework) + if ( Boost_FOUND ) include_directories (${Boost_INCLUDE_DIRS}) - file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cpp) + file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) foreach(testSrc ${TEST_SRCS}) get_filename_component(testName ${testSrc} NAME_WE) add_executable(${testName} ${testSrc}) diff --git a/test/test_AmplitudeRules.cpp b/test/test_AmplitudeRules.cpp index 08a704eb007..043950d5f9a 100644 --- a/test/test_AmplitudeRules.cpp +++ b/test/test_AmplitudeRules.cpp @@ -23,18 +23,19 @@ BOOST_AUTO_TEST_CASE( test_AmplitudeRule ) { BOOST_CHECK( test.prefix() == "" ); BOOST_CHECK( test.eventType() == EventType({"D0","K-","pi+","pi0"}) ); } -AmplitudeRules rule_set( - MinuitParameterSet( { - new MinuitParameter("D0{K*(892)bar0,pi0}_Re", Flag::Fix,1.,0.) - , new MinuitParameter("D0{K*(892)bar0,pi0}_Im", Flag::Fix,1.,0.) - , new MinuitParameter("D0{rho(770)+,pi-}_Re" , Flag::Fix,1.,0.) - , new MinuitParameter("D0{rho(770)+,pi-}_Im" , Flag::Fix,2.,0.) - , new MinuitParameter("K*(892)bar0{K-,pi+}_Re", Flag::Free,sqrt(1./3.),0.) - , new MinuitParameter("K*(892)bar0{K-,pi+}_Im", Flag::Free,0,0.) - , new MinuitParameter("K*(892)bar0{K0,pi0}_Re", Flag::Fix,sqrt(2./3.),0.) - , new MinuitParameter("K*(892)bar0{K0,pi0}_Im", Flag::Fix,0,0.) } ) ); BOOST_AUTO_TEST_CASE( test_AmplitudeRules_constructor ){ + auto mps = MinuitParameterSet( { + new MinuitParameter("D0{K*(892)bar0,pi0}_Re", Flag::Fix,1.,0.) + , new MinuitParameter("D0{K*(892)bar0,pi0}_Im", Flag::Fix,1.,0.) + , new MinuitParameter("D0{rho(770)+,pi-}_Re" , Flag::Fix,1.,0.) + , new MinuitParameter("D0{rho(770)+,pi-}_Im" , Flag::Fix,2.,0.) + , new MinuitParameter("K*(892)bar0{K-,pi+}_Re", Flag::Free,sqrt(1./3.),0.) + , new MinuitParameter("K*(892)bar0{K-,pi+}_Im", Flag::Free,0,0.) + , new MinuitParameter("K*(892)bar0{K0,pi0}_Re", Flag::Fix,sqrt(2./3.),0.) + , new MinuitParameter("K*(892)bar0{K0,pi0}_Im", Flag::Fix,0,0.) } ); + AmplitudeRules rule_set(mps); + BOOST_CHECK( rule_set.rules().size() == 2 ); /// number of head decays BOOST_CHECK( rule_set.hasDecay("D0") == true ); /// has decays for D0 BOOST_CHECK( rule_set.hasDecay("a(1)(1260)+") == false ); /// has decays for D0 @@ -42,9 +43,19 @@ BOOST_AUTO_TEST_CASE( test_AmplitudeRules_constructor ){ BOOST_AUTO_TEST_CASE( test_couplingConstant ) { + auto mps = MinuitParameterSet( { + new MinuitParameter("D0{K*(892)bar0,pi0}_Re", Flag::Fix,1.,0.) + , new MinuitParameter("D0{K*(892)bar0,pi0}_Im", Flag::Fix,1.,0.) + , new MinuitParameter("D0{rho(770)+,pi-}_Re" , Flag::Fix,1.,0.) + , new MinuitParameter("D0{rho(770)+,pi-}_Im" , Flag::Fix,2.,0.) + , new MinuitParameter("K*(892)bar0{K-,pi+}_Re", Flag::Free,sqrt(1./3.),0.) + , new MinuitParameter("K*(892)bar0{K-,pi+}_Im", Flag::Free,0,0.) + , new MinuitParameter("K*(892)bar0{K0,pi0}_Re", Flag::Fix,sqrt(2./3.),0.) + , new MinuitParameter("K*(892)bar0{K0,pi0}_Im", Flag::Fix,0,0.) } ); + AmplitudeRules rule_set(mps); auto matches = rule_set.getMatchingRules( EventType({"D0","K-","pi+","pi0"}) ); auto matches2 = rule_set.getMatchingRules( EventType({"D0","K0","pi0","pi0"}) ); - + BOOST_TEST( std::real(matches[0].second()) == 1./sqrt(3.), boost::test_tools::tolerance(1e-10) ); BOOST_TEST( std::imag(matches[0].second()) == 1./sqrt(3.), boost::test_tools::tolerance(1e-10) ); BOOST_TEST( matches[0].second.isFixed() == false ); diff --git a/test/test_ExpressionParser.cpp b/test/test_ExpressionParser.cpp index d6657a1c6c0..2430f1fcda8 100644 --- a/test/test_ExpressionParser.cpp +++ b/test/test_ExpressionParser.cpp @@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE( parametericExpressions ) { double pi = M_PI; - auto test = [mps](const std::string& expr) -> double { + auto test = [&mps](const std::string& expr) -> double { std::string newLine=""; for( auto& ch : expr ){ if( ch == '(' || From 286698ace253cc5352d94760819c8e005d40653f Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 5 Mar 2020 20:05:26 +0100 Subject: [PATCH 161/250] Update mass_width.csv --- options/mass_width.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/mass_width.csv b/options/mass_width.csv index 4833cbc1c7e..8f69cb84e84 100644 --- a/options/mass_width.csv +++ b/options/mass_width.csv @@ -382,7 +382,7 @@ 2.3178E+03 ,6.0E-01,6.0E-01,10 ,-1 ,-1 ,0 , ,0 ,+, ,B, 10431, +, ,R,D(s0)*(2317) ,cS 2.4596E+03 ,6.0E-01,6.0E-01,6.3 ,-1 ,-1 ,0 , ,1 ,+, ,B, 20433, +, ,R,D(s1)(2460) ,cS 2.5354E+03 ,6.0E-01,6.0E-01,2.5 ,-1 ,-1 ,0 , ,1 ,+, ,B, 10433, +, ,R,D(s1)(2536) ,cS -2.5726E+03 ,9.0E-01,9.0E-01,2.0E+01 ,5.0E+00,5.0E+00,0 , ,? ,?, ,B, 435, +, ,R,D(s2)(2573) ,cS +2.5726E+03 ,9.0E-01,9.0E-01,2.0E+01 ,5.0E+00,5.0E+00,0 , ,2 ,+, ,B, 435, +, ,R,D(s2)(2573) ,cS 2.690E+03 ,7.0E+00,7.0E+00,1.10E+02 ,2.7E+01,2.7E+01,0 , ,1 ,-, ,B, , +, ,S,D(s1)(2700) ,cS 5.27915E+03 ,3.1E-01,3.1E-01,4.045E-10 ,2.7E-12,2.7E-12,1/2, ,0 ,-, ,B, 521, +, ,R,B ,uB 5.27953E+03 ,3.3E-01,3.3E-01,4.331E-10 ,2.5E-12,2.5E-12,1/2, ,0 ,-, ,F, 511, 0, ,R,B ,dB From 75989979ed4b32e3c73d8fa687b9538b661b8862 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 17 Mar 2020 17:46:41 +0100 Subject: [PATCH 162/250] commit with speed up integration / partially modernised caching --- AmpGen/AmplitudeRules.h | 13 +- AmpGen/BinDT.h | 24 ++-- AmpGen/Chi2Estimator.h | 9 +- AmpGen/CoherentSum.h | 8 +- AmpGen/CompiledExpression.h | 15 ++- AmpGen/CompiledExpressionBase.h | 4 +- AmpGen/Event.h | 1 + AmpGen/EventList.h | 41 ++++--- AmpGen/FitFraction.h | 5 +- AmpGen/Integrator.h | 17 ++- AmpGen/Integrator2.h | 31 +++-- AmpGen/LiteSpan.h | 74 ++++++++++++ AmpGen/NamedParameter.h | 2 +- AmpGen/Particle.h | 1 + AmpGen/PolarisedSum.h | 31 ++--- AmpGen/Projection.h | 29 +++-- AmpGen/SumPDF.h | 23 +++- AmpGen/Utilities.h | 9 +- apps/Fitter.cpp | 7 +- apps/Generator.cpp | 4 +- examples/FitterWithPolarisation.cpp | 32 ++--- examples/SignalOnlyFitter.cpp | 39 +++--- examples/SimFit.cpp | 4 +- src/AmplitudeRules.cpp | 2 +- src/BinDT.cpp | 20 +++- src/Chi2Estimator.cpp | 17 +-- src/CoherentSum.cpp | 55 ++++++++- src/CompiledExpressionBase.cpp | 2 +- src/Event.cpp | 2 +- src/EventList.cpp | 50 +++----- src/FitFraction.cpp | 2 - src/Integrator2.cpp | 13 +- src/PolarisedSum.cpp | 178 +++++++++++++++++++--------- src/Projection.cpp | 35 +++++- 34 files changed, 537 insertions(+), 262 deletions(-) create mode 100644 AmpGen/LiteSpan.h diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index e3a18d0f6c1..2dbb64ed0db 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -73,7 +73,7 @@ namespace AmpGen AmplitudeRules( const MinuitParameterSet& mps ); std::vector rulesForDecay(const std::string& head, const std::string& prefix=""); bool hasDecay( const std::string& head ); - std::map> rules(); + const std::map>& rules() const; std::vector> getMatchingRules( const EventType& type, const std::string& prefix="" ); std::vector processesThatProduce(const Particle& particle) const; @@ -113,8 +113,7 @@ namespace AmpGen size_t addressData = {999}; }; - template - std::vector processIndex(const std::vector>& tm, const std::string& label) + template std::vector processIndex(const std::vector>& tm, const std::string& label) { std::vector indices; for ( size_t i = 0; i < tm.size(); ++i ) { @@ -123,8 +122,7 @@ namespace AmpGen return indices; } - template - size_t findIndex(const std::vector>& tm, const std::string& decayDescriptor) + template size_t findIndex(const std::vector>& tm, const std::string& decayDescriptor) { for ( size_t i = 0; i < tm.size(); ++i ) { if ( tm[i].decayDescriptor() == decayDescriptor ) return i; @@ -163,12 +161,12 @@ namespace AmpGen amp(decayTree.getExpression(debugThis ? &db : nullptr ), decayTree.decayDescriptor(), evtFormat, db, &mps ) { amp.use_rto();} const std::vector operator()(const Event& event) const { - std::vector rt; + std::vector rt(4); amp(rt.data(), amp.externBuffer().data(), event.address() ); return rt; } const std::vector operator()(const Event& event, const size_t& cacheOffset) const { - std::vector rt; + std::vector rt(4); amp(rt.data(), amp.externBuffer().data(), event.address() + cacheOffset); return rt; } @@ -180,6 +178,7 @@ namespace AmpGen DebugSymbols db; CompiledExpression amp; size_t addressData = {999}; + bool workToDo = {false}; }; } // namespace AmpGen diff --git a/AmpGen/BinDT.h b/AmpGen/BinDT.h index 58795770a6a..5a29f25aefd 100644 --- a/AmpGen/BinDT.h +++ b/AmpGen/BinDT.h @@ -69,7 +69,9 @@ namespace AmpGen void serialize( std::ostream& stream ) const override; void setChildren( std::shared_ptr l, std::shared_ptr r ); void visit( const std::function& visit_function ) override; + friend class BinDT; + private : std::shared_ptr m_left; std::shared_ptr m_right; @@ -87,22 +89,12 @@ namespace AmpGen { m_top = makeNodes( addr ); } - template - BinDT( const EventList& events, const ARGS&... args ) : BinDT( ArgumentPack( args... ) ) + template BinDT( const EventList& events, const ARGS&... args ) : BinDT(ArgumentPack( args... ) ) { - std::vector data( m_dim * events.size() ); - std::vector addresses( events.size() ); - size_t counter = 0; - for ( auto& evt : events ) { - auto val = m_functors( evt ); - for ( unsigned int i = 0; i < m_dim; ++i ) data[m_dim * counter + i] = val[i]; - addresses[counter] = &( data[m_dim * counter] ); - counter++; - } - INFO( "Making nodes" ); - m_top = makeNodes( addresses ); + m_top = makeNodes( events ); } explicit BinDT( const ArgumentPack& args ); + BinDT( const EventList& events, const ArgumentPack& args ); BinDT() = default; std::shared_ptr top() { return m_top; } @@ -122,19 +114,19 @@ namespace AmpGen std::function( const Event& )> makeDefaultFunctors(); void refreshQueue(const std::vector&, std::queue&, const unsigned&); + std::shared_ptr makeNodes(const EventList&); std::shared_ptr makeNodes(const std::vector&, std::queue, const unsigned&); std::shared_ptr makeNodes(const std::vector&); std::shared_ptr makeNodes(const std::vector&, const std::vector&); std::shared_ptr makeNodes(std::vector, std::vector, std::queue, const unsigned&); void setFunctor(const std::function( const Event& )>& functors) { m_functors = functors; } - private: std::shared_ptr m_top = {nullptr}; unsigned m_dim = {0}; unsigned m_minEvents = {0}; unsigned m_maxDepth = {0}; - std::vector m_queueOrdering = {}; - std::vector> m_endNodes = {}; + std::vector m_queueOrdering = {}; + std::vector> m_endNodes = {}; std::function(const Event&)> m_functors = {}; double getBestPost(const std::vector& source, const std::vector& target, int index, bool verbose = false ); }; diff --git a/AmpGen/Chi2Estimator.h b/AmpGen/Chi2Estimator.h index 9102cbdb7dc..4f59291ca85 100644 --- a/AmpGen/Chi2Estimator.h +++ b/AmpGen/Chi2Estimator.h @@ -16,11 +16,14 @@ namespace AmpGen class Chi2Estimator { public: + template Chi2Estimator( const EventList& dataEvents, const EventList& mcEvents, - const std::function& fcn, const unsigned int& minEvents = 10 ); + const std::function& fcn, + const argument_types&... args ) : m_binning(dataEvents, ArgumentPack(args...) ) + { + doChi2(dataEvents, mcEvents, fcn); + } - Chi2Estimator( const EventList& dataEvents, const EventList& mcEvents, - const std::function& fcn, const std::string& filename ); double chi2() const; double nBins() const; void writeBinningToFile( const std::string& filename ); diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index 0ceff448770..514c5d0d46f 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -86,13 +86,15 @@ namespace AmpGen std::map> getGroupedAmplitudes(); Bilinears norms() const { return m_normalisations ; } - + + std::function evaluator(const EventList* = nullptr) const; + KeyedView componentEvaluator(const EventList* = nullptr) const; + protected: - typedef Integrator<10> integrator; std::vector> m_matrixElements; ///< Vector of (expanded) matrix elements Bilinears m_normalisations; ///< Normalisation integrals AmplitudeRules m_rules; ///< Ruleset for the selected transition. - integrator m_integrator; ///< Integral dispatch tool (with default unroll = 10) + Integrator2 m_integrator; ///< Integral dispatch tool (with default unroll = 10) TransitionMatrix m_total; ///< Total Matrix Element EventList* m_events = {nullptr}; ///< Data events to evaluate PDF on EventType m_evtType; ///< Final state for this amplitude diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index 8fe90dce51a..d3289d6c4a6 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -23,7 +23,9 @@ namespace AmpGen (i.e. returning array types) */ namespace detail { template struct size_of { unsigned operator()(){ return sizeof(T); } }; - template <> struct size_of { unsigned operator()(){ return 0; } }; + template <> struct size_of { unsigned operator()(){ + WARNING("Asking for the size_of the return buffer of an RTO expression"); + return 0; } }; } template @@ -37,6 +39,7 @@ namespace AmpGen bool m_hasExternalsChanged = {false}; public: + typedef RETURN_TYPE return_type; CompiledExpression( const Expression& expression, const std::string& name, @@ -54,7 +57,10 @@ namespace AmpGen std::string returnTypename() const override { return typeof(); } std::string fcnSignature() const override { - return CompiledExpressionBase::fcnSignature(typelist(), m_rto); + return CompiledExpressionBase::fcnSignature(typelist(), use_rto()); + } + bool use_rto() const override { + return std::is_same::value; } std::string args() const override { @@ -145,7 +151,9 @@ namespace AmpGen if ( !m_fdb.isLinked() ) { FATAL( "Function" << name() << " debugging symbols not linked" ); } - auto debug_results = m_fdb( &( m_externals[0] ), event ); + std::vector> debug_results; + if constexpr(std::is_same::value) debug_results = m_fdb( nullptr, &( m_externals[0] ), event ); + else debug_results = m_fdb( &(m_externals[0]), event); for( auto& debug_result : debug_results ){ auto val = debug_result.second; auto label = debug_result.first; @@ -192,7 +200,6 @@ namespace AmpGen make_rto_expression( const Expression& expression, const std::string& name , const bool& verbose=false) { CompiledExpression rt(expression,name); - rt.use_rto(); rt.compile(); rt.prepare(); return rt; diff --git a/AmpGen/CompiledExpressionBase.h b/AmpGen/CompiledExpressionBase.h index 6643d47d97f..d1e26ea9a7a 100644 --- a/AmpGen/CompiledExpressionBase.h +++ b/AmpGen/CompiledExpressionBase.h @@ -57,7 +57,8 @@ namespace AmpGen virtual ~CompiledExpressionBase(); virtual unsigned returnTypeSize() const = 0; static std::string fcnSignature(const std::vector& argList, bool rto); - void use_rto(){ m_rto = true; } + virtual bool use_rto() const = 0; + Expression expression() const { return m_obj; } protected: Expression m_obj; std::string m_name; @@ -68,7 +69,6 @@ namespace AmpGen std::vector> m_debugSubexpressions; std::vector> m_cacheTransfers; std::shared_ptr m_resolver; - bool m_rto = {false}; private: void addDebug( std::ostream& stream ) const; void addDependentExpressions( std::ostream& stream, size_t& sizeOfStream ) const; diff --git a/AmpGen/Event.h b/AmpGen/Event.h index 53e2aed3d18..bf168f02cd3 100644 --- a/AmpGen/Event.h +++ b/AmpGen/Event.h @@ -51,6 +51,7 @@ namespace AmpGen { const complex_t& getCache(const unsigned& pos) const { return m_cache[pos]; } const complex_t* getCachePtr(const unsigned& pos=0) const { return &(m_cache[0]) + pos; } + complex_t* getCachePtr(const unsigned& pos=0) { return &(m_cache[0]) + pos; } void setWeight( const real_t& weight ){ m_weight = weight ; } void setGenPdf( const real_t& genPdf ){ m_genPdf = genPdf ; } diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 01e739042ba..131af735ea0 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -25,9 +25,7 @@ namespace AmpGen { - - DECLARE_ARGUMENT(Bins, size_t); - + namespace PlotOptions { DECLARE_ARGUMENT(Bins, size_t); } class CompiledExpressionBase; class EventList { @@ -36,7 +34,6 @@ namespace AmpGen EventType m_eventType = {}; std::map m_pdfIndex = {}; std::map m_extensions = {}; - double m_norm = {0}; size_t m_lastCachePosition = {0}; public: typedef Event value_type; @@ -74,7 +71,6 @@ namespace AmpGen const Event& at( const size_t& pos ) const { return m_data[pos]; } size_t size() const { return m_data.size(); } double integral() const; - double norm(); void reserve( const size_t& size ) { m_data.reserve( size ); } void push_back( const Event& evt ) { m_data.push_back( evt ); } @@ -86,7 +82,7 @@ namespace AmpGen void clear(); void erase( const std::vector::iterator& begin, const std::vector::iterator& end ); - TTree* tree( const std::string& name, const std::vector& extraBranches = {} ); + TTree* tree( const std::string& name, const std::vector& extraBranches = {} ) const; size_t getCacheIndex( const CompiledExpressionBase& PDF, bool& status ) const; size_t getCacheIndex( const CompiledExpressionBase& PDF ) const; @@ -113,15 +109,25 @@ namespace AmpGen } } - template - void updateCache( const FCN& fcn, const size_t& index ) + template void updateCache( const FCN& fcn, const size_t& index ) { - #ifdef _OPENMP - #pragma omp parallel for - #endif - for ( unsigned int i = 0; i < size(); ++i ) { - ( *this )[i].setCache(fcn(getEvent(i)), index); + if constexpr( std::is_same< typename FCN::return_type, void >::value ) + { + #ifdef _OPENMP + #pragma omp parallel for + #endif + for ( size_t i = 0; i < size(); ++i ) { + fcn( m_data[i].getCachePtr(index), fcn.externBuffer().data(), m_data[i].address() ); + } } + else { + #ifdef _OPENMP + #pragma omp parallel for + #endif + for ( size_t i = 0; i < size(); ++i ) { + m_data[i].setCache(fcn(m_data[i].address()), index); + } + } } void reserveCache(const size_t& index); void resizeCache(const size_t& newCacheSize ); @@ -132,7 +138,7 @@ namespace AmpGen template std::vector makeDefaultProjections( const ARGS&... args ) { auto argPack = ArgumentPack( args... ); - size_t nBins = argPack.getArg(100); + size_t nBins = argPack.getArg(100); auto proj = eventType().defaultProjections(nBins); return makeProjections( proj , argPack ); } @@ -174,10 +180,6 @@ namespace AmpGen return std::count_if( std::begin(*this), std::end(*this), fcn ); } }; - DECLARE_ARGUMENT(LineColor, int); - DECLARE_ARGUMENT(DrawStyle, std::string); - DECLARE_ARGUMENT(Selection, std::function); - DECLARE_ARGUMENT(WeightFunction, std::function); DECLARE_ARGUMENT(Branches, std::vector); DECLARE_ARGUMENT(EntryList, std::vector); DECLARE_ARGUMENT(GetGenPdf, bool); @@ -185,7 +187,8 @@ namespace AmpGen DECLARE_ARGUMENT(Filter, std::string); DECLARE_ARGUMENT(WeightBranch, std::string); DECLARE_ARGUMENT(ApplySym, bool); - DECLARE_ARGUMENT(Prefix, std::string); + DECLARE_ARGUMENT(WeightFunction, std::function); + } // namespace AmpGen #endif diff --git a/AmpGen/FitFraction.h b/AmpGen/FitFraction.h index cabdb99767c..88efd3af8c5 100644 --- a/AmpGen/FitFraction.h +++ b/AmpGen/FitFraction.h @@ -7,6 +7,7 @@ #include #include "AmpGen/Types.h" #include "AmpGen/ErrorPropagator.h" +#include "AmpGen/AmplitudeRules.h" namespace AmpGen { @@ -24,7 +25,6 @@ namespace AmpGen double val() const; double err() const; std::string name() const; - std::shared_ptr particle() const; private: std::string m_name; @@ -60,7 +60,8 @@ namespace AmpGen pdf(pdf), normSet(normSet), recalculateIntegrals(recalculateIntegrals) {} - std::vector operator()(){ + std::vector operator()() + { if ( recalculateIntegrals ) pdf->prepare(); else pdf->transferParameters(); std::vector rv; diff --git a/AmpGen/Integrator.h b/AmpGen/Integrator.h index 7f16be8d0f8..5312012b13b 100644 --- a/AmpGen/Integrator.h +++ b/AmpGen/Integrator.h @@ -51,7 +51,7 @@ namespace AmpGen Integral(const size_t& i, const size_t& j, TransferFCN t) : i(i), j(j), transfer(t) {} }; - +/* template class Integrator { @@ -87,10 +87,11 @@ namespace AmpGen public: Integrator( EventList* events = nullptr ) : m_events( events ){} - double sampleNorm() { return m_events->norm(); } + double norm() { return m_events->norm(); } bool isReady() const { return m_events != nullptr; } EventList& events() { return *m_events; } const EventList& events() const { return *m_events; } + void reserveCache(const unsigned& size){ m_events->reserveCache(size); } template void addIntegral( const T1& f1, const T2& f2, const Integral::TransferFCN& tf ) { @@ -136,7 +137,7 @@ namespace AmpGen return m_events->getCacheIndex(expression); } }; - + */ template class BinnedIntegrator { @@ -149,6 +150,7 @@ namespace AmpGen std::vector m_slice = {0}; std::array, NROLL> m_integrals; EventList* m_events = {nullptr}; + real_t m_norm = {0}; void calculate() { integrateBlock(); @@ -187,17 +189,20 @@ namespace AmpGen } } } - double nv = m_events->norm(); for ( size_t thisIntegral = 0; thisIntegral < m_counter; ++thisIntegral ) { std::vector> tmpBins( NBINS ); size_t offset = thisIntegral * NBINS; for ( size_t nBin = 0; nBin < NBINS; ++nBin ) - tmpBins[nBin] = std::complex( re[offset + nBin], im[offset + nBin] ) / nv; + tmpBins[nBin] = std::complex( re[offset + nBin], im[offset + nBin] ) / m_norm; m_integrals[thisIntegral].transfer( tmpBins ); } } public: - BinnedIntegrator( EventList* events = nullptr ) : m_events( events ) {} + BinnedIntegrator( EventList* events = nullptr ) : m_events( events ) + { + if( m_events == nullptr ) return; + for ( const auto& event : *m_events ) m_norm += event.weight() / event.genPdf(); + } void setView( const std::function& binNumber ) { if ( m_slice.size() == 0 ) { diff --git a/AmpGen/Integrator2.h b/AmpGen/Integrator2.h index d8f7742c37d..f13efd1ad6f 100644 --- a/AmpGen/Integrator2.h +++ b/AmpGen/Integrator2.h @@ -26,7 +26,9 @@ namespace AmpGen { void flush(); void setBuffer( complex_t* pos, const complex_t& value, const size_t& size ); void setBuffer( complex_t* pos, const std::vector& value, const size_t& size); - + void reserveCache(const unsigned int& size){}; + complex_t get(const unsigned& i, const unsigned& evt) const { return m_buffer[i][evt]; } + double norm() const { return m_norm; } template size_t getCacheIndex(const T& expression) const { return m_index.find(expression.name())->second; @@ -42,17 +44,28 @@ namespace AmpGen { index = m_buffer.size(); m_index[ expression.name() ] = index; m_buffer.resize(index+vsize); - for(size_t j = 0 ; j != vsize; ++j ) - m_buffer[index+j].resize( m_events->size() ); + for(size_t j = 0 ; j != vsize; ++j ) m_buffer[index+j].resize( m_events->size() ); } else index = it->second; - #ifdef _OPENMP - #pragma omp parallel for - #endif - for ( size_t i = 0; i < m_events->size(); ++i ) + if constexpr( std::is_same< typename T::return_type, void >::value ) { - auto v = expression(m_events->at(i).address()); - setBuffer( &(m_buffer[index][i]), v, vsize ); + #ifdef _OPENMP + #pragma omp parallel for + #endif + for ( size_t i = 0; i < m_events->size(); ++i ) + { + std::vector buf(vsize); + expression(&buf[0], expression.externBuffer().data(), m_events->at(i).address() ); + for( unsigned j = 0; j != vsize; ++j ) m_buffer[index+j][i] = buf[j]; + //expression(&(m_buffer[index][i]), expression.externBuffer().data(), m_events->at(i).address() ); + } + } + else { + #ifdef _OPENMP + #pragma omp parallel for + #endif + for ( size_t i = 0; i < m_events->size(); ++i ) + setBuffer( &(m_buffer[index][i]), expression(m_events->at(i).address()), vsize ); } } diff --git a/AmpGen/LiteSpan.h b/AmpGen/LiteSpan.h new file mode 100644 index 00000000000..ac1a4548d60 --- /dev/null +++ b/AmpGen/LiteSpan.h @@ -0,0 +1,74 @@ +#ifndef AMPGEN_LITESPAN_H +#define AMPGEN_LITESPAN_H + +#include "AmpGen/MsgService.h" +#include "AmpGen/Utilities.h" + +namespace AmpGen { + // replace with std::span when c++20 becomes widespread + template class LiteSpan + { + public: + LiteSpan( const type* data, unsigned size =1) : m_data(data), m_size(size) {} + const type& operator[](const unsigned index) const { return m_data[index]; } + operator type() const { return m_data[0] ; } + unsigned size() const { return m_size; } + private: + const type* m_data = {nullptr}; + unsigned m_size = {0}; + }; + /// functor-like object that documents what is stored in each slot; + /// This mutated into a cache-like object as was I was writing it, so + /// should rename it to something else ... + template class KeyedView + { + typedef typename container_type::value_type value_type; + public: + KeyedView( const container_type& container, const unsigned width ) : + m_begin( &(container[0]) ), + m_cache( width * container.size(),0 ), + m_width(width), + m_size(container.size()), + m_keys( width, "") {} + unsigned index(const value_type& it) const { + if( &it - m_begin < 0 || &it -m_begin >= m_size ) ERROR("Invalid address: " << &it - m_begin ); + return &it -m_begin; } + const std::string& key(const unsigned int& column ) const { return m_keys[column] ; } + const return_type* operator()( const value_type& it ) const { + if( m_width *index(it) >= m_cache.size()) ERROR("Out-of-bounds access : " << index(it) ); + return &m_cache[m_width * index(it)]; } + const cache_type& operator()(const value_type& it, const unsigned entry ) const { + if( m_width * index(it) + entry > m_cache.size() ) ERROR("Invalid cache element: " << m_width * index(it) + entry > m_cache.size() ); + return m_cache[m_width * index(it) + entry] ; } + unsigned width() const { return m_width ; } + + template void set(const functor_type& functor, + unsigned int column, + const std::string& key = "") + { + for( unsigned i = 0 ; i != m_size; ++i ) m_cache[ i*m_width + column] = functor(m_begin[i]); + if( key != "" ) m_keys[column] = key; + } + cache_type& operator()(const value_type& it, const unsigned entry ) { + auto pos = m_width * index(it) + entry; + if( pos >= m_cache.size() ) ERROR("Out-of-bounds access: " << pos << " " << index(it) + entry); + return m_cache[pos] ; } + void setKey(const unsigned& column, const std::string& key ) { m_keys[column] = key ; } + void print() + { + INFO( "width = " << m_width << ", size = " << m_size << " begin = " << m_begin << " keys = " << vectorToString( m_keys , " ") << " cache size = " << m_cache.size() ); + for( unsigned int i = 0 ; i != m_width ; ++i ) std::cout << m_cache[i] << " "; + } + private: + const value_type* m_begin; + std::vector m_cache; + unsigned m_width; + unsigned m_size; + std::vector m_keys; + }; + +} + +#endif diff --git a/AmpGen/NamedParameter.h b/AmpGen/NamedParameter.h index 374ff4b3fb5..461b33c4bd3 100644 --- a/AmpGen/NamedParameter.h +++ b/AmpGen/NamedParameter.h @@ -74,7 +74,7 @@ namespace AmpGen setFromOptionsParser(); if ( OptionsParser::printHelp() ) help( defVec.size() > 0 ? defVec[0] : T() ); } - +// ~NamedParameter(){ INFO("Deconstructing: " << m_name ); } void help(const T& def){ std::string type = typeof(); if( type == "std::__cxx11::basic_string, std::allocator >" ) type = "string"; diff --git a/AmpGen/Particle.h b/AmpGen/Particle.h index 15577818f98..9dd3609d1b6 100644 --- a/AmpGen/Particle.h +++ b/AmpGen/Particle.h @@ -276,6 +276,7 @@ namespace AmpGen /// matches Check the matching between two decay chains, according to the MatchState enum. unsigned int matches( const Particle& other ) const; std::string makeUniqueString(); ///< Generate the decay descriptor for this decay. + private: std::string m_name = {""}; ///< Name of the particle const ParticleProperties* m_props = {nullptr}; ///< Particle Properties from the PDG diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index a6c002ac73b..0cc662c728d 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -35,35 +35,36 @@ namespace AmpGen class PolarisedSum { public: - typedef Integrator<10> integrator; + typedef Integrator2 integrator; PolarisedSum() = default; - PolarisedSum(const EventType&, AmpGen::MinuitParameterSet&, const std::vector& = {}); + PolarisedSum(const EventType&, MinuitParameterSet&, const std::vector& = {}); void prepare(); - void setEvents(AmpGen::EventList&); - void setMC(AmpGen::EventList&); + void setEvents(EventList&); + void setMC(EventList&); void reset(const bool& = false); - void debug(const AmpGen::Event&); + void debug(const Event&); void debug_norm(); void setWeight(MinuitProxy); double getWeight() const; - void calculateNorms(const std::vector&); + void calculateNorms(); void generateSourceCode(const std::string&, const double& = 1, bool = false); void build_probunnormalised(); Expression probExpression(const Tensor&, const std::vector&, DebugSymbols* = nullptr) const; size_t size() const; real_t norm() const; complex_t norm(const size_t&, const size_t&, integrator* = nullptr); - inline real_t operator()(const AmpGen::Event& evt) const { return m_weight * prob_unnormalised(evt) / m_norm; } - real_t prob_unnormalised(const AmpGen::Event&) const; - real_t prob(const AmpGen::Event&) const; - real_t getValNoCache(const AmpGen::Event&) ; + inline real_t operator()(const Event& evt) const { return m_weight * prob_unnormalised(evt) / m_norm; } + real_t prob_unnormalised(const Event&) const; + real_t prob(const Event&) const; + real_t getValNoCache(const Event&) ; std::vector fitFractions(const LinearErrorPropagator&); - std::vector>> matrixElements() const; + std::vector> matrixElements() const; void transferParameters(); Tensor transitionMatrix(); - TransitionMatrix> operator[](const size_t& i) const { return m_matrixElements[i] ; } - + const TransitionMatrix& operator[](const size_t& i) const { return m_matrixElements[i] ; } + std::function evaluator(const EventList* = nullptr) const; + KeyedView componentEvaluator(const EventList* = nullptr) const; private: size_t m_nCalls = {0}; real_t m_norm = {1}; @@ -81,9 +82,9 @@ namespace AmpGen std::vector m_integIndex; AmplitudeRules m_rules; std::pair m_dim; - std::vector>> m_matrixElements; + std::vector> m_matrixElements; CompiledExpression m_probExpression; - + std::vector> indexProduct(const std::vector>&, const std::vector&) const; std::vector polarisations(const std::string&) const ; }; diff --git a/AmpGen/Projection.h b/AmpGen/Projection.h index 6f14beeaee0..53730e4de3e 100644 --- a/AmpGen/Projection.h +++ b/AmpGen/Projection.h @@ -8,10 +8,10 @@ #include "TH1D.h" #include "TH2D.h" -#include "AmpGen/ArgumentPack.h" +#include "THStack.h" -class TH1D; -class TH2D; +#include "AmpGen/ArgumentPack.h" +#include "AmpGen/LiteSpan.h" namespace AmpGen { @@ -31,18 +31,26 @@ namespace AmpGen const std::string& xAxisTitle, const size_t& nBins, const double& min, const double& max, const std::string& units = "" ); const std::string name() const; - template TH1D* operator()(const EventList& evt, const ARGS... args) const { return projInternal(evt, ArgumentPack(args...) ); } - + template TH1D* operator()(const EventList& evt, const ARGS... args) const + { + return projInternal(evt, ArgumentPack(args...) ); + } + template std::tuple, THStack*> operator()(const EventList& evt, const KeyedView& weightFunction, const ARGS... args ) const + { + return projInternal(evt, weightFunction, ArgumentPack(args...) ); + } + double operator()( const Event& evt ) const; TH1D* plot(const std::string& prefix="") const; - std::function binFunctor() const; + std::function binFunctor() const; void setRange( const double& min, const double& max ){ m_min = (min); m_max = (max) ; } friend class Projection2D; private: TH1D* projInternal(const EventList&, const ArgumentPack&) const; + std::tuple, THStack*> projInternal(const EventList&, const KeyedView&, const ArgumentPack&) const; std::function m_func; std::string m_name = {""}; std::string m_xAxisTitle = {""}; @@ -66,7 +74,14 @@ namespace AmpGen std::pair operator()( const Event& evt ) const; }; - + namespace PlotOptions { + DECLARE_ARGUMENT(LineColor , int); + DECLARE_ARGUMENT(DrawStyle , std::string); + DECLARE_ARGUMENT(Selection , std::function); + DECLARE_ARGUMENT(Prefix , std::string); + DECLARE_ARGUMENT(Norm , double); + DECLARE_ARGUMENT(AddTo , THStack*); + } } // namespace AmpGen #endif diff --git a/AmpGen/SumPDF.h b/AmpGen/SumPDF.h index dbce73fcdff..3388560266d 100644 --- a/AmpGen/SumPDF.h +++ b/AmpGen/SumPDF.h @@ -5,7 +5,7 @@ #include "AmpGen/MetaUtils.h" #include "AmpGen/MsgService.h" #include "AmpGen/ProfileClock.h" - +#include "AmpGen/LiteSpan.h" #include namespace AmpGen @@ -65,7 +65,7 @@ namespace AmpGen double operator()( const eventValueType& evt ) { double prob = 0; - for_each( this->m_pdfs, [&prob, &evt]( auto& f ) { prob += f(evt); } ); + for_each( this->m_pdfs, [&prob, &evt]( const auto& f ) { prob += f(evt); } ); return prob; } @@ -81,6 +81,25 @@ namespace AmpGen /// Returns the tuple of PDFs used by this function std::tuple pdfs() const { return m_pdfs; } + + std::function evaluator(const eventListType* events) const + { + std::vector values( events->size() ); + for_each( this->m_pdfs, [events, &values](const auto& pdf ) mutable { + auto eval = pdf.evaluator(events); + for( unsigned i = 0; i != events->size(); ++i ) values[i] += eval( events->at(i) ); + } ); + return arrayToFunctor(values, events); + } + KeyedView componentEvaluator(const eventListType* events) const + { + KeyedView view(*events, nPDFs() ); + unsigned pdf_counter = 0; + for_each( this->m_pdfs, [&events, &view, &pdf_counter](const auto& pdf) mutable { + view.set(pdf.evaluator(events), pdf_counter++, typeof(pdf) ); + } ); + return view; + } }; /** @function make_pdf diff --git a/AmpGen/Utilities.h b/AmpGen/Utilities.h index b321773df16..929c55c558f 100644 --- a/AmpGen/Utilities.h +++ b/AmpGen/Utilities.h @@ -19,7 +19,6 @@ #include "AmpGen/MsgService.h" #include "AmpGen/MetaUtils.h" - namespace AmpGen { template std::string vectorToString( it_type begin, @@ -162,6 +161,14 @@ namespace AmpGen { } return total; } + template std::function + arrayToFunctor( const std::vector& values, const container_type* container ) + { + return [container, values](const typename container_type::value_type& event) -> return_type { + int addr = &event - &container->at(0); + return *(values.data() + addr); }; + } template void parallel_sort(iterator begin, diff --git a/apps/Fitter.cpp b/apps/Fitter.cpp index d05d1430ba9..a1dedbb40b7 100644 --- a/apps/Fitter.cpp +++ b/apps/Fitter.cpp @@ -129,12 +129,11 @@ FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& if ( makePlots ) { auto ep = fr->getErrorPropagator(); -// const size_t NBins = NamedParameter ("nBins" , 100 , "Number of bins used for plotting."); unsigned int counter = 1; for_each( pdf.pdfs(), [&]( auto& f ) { auto tStartIntegral2 = std::chrono::high_resolution_clock::now(); - auto mc_plot3 = mc.makeProjections( mc.eventType().defaultProjections(100), WeightFunction(f), Prefix("tMC_Category"+std::to_string(counter) ) ); + auto mc_plot3 = mc.makeProjections( mc.eventType().defaultProjections(100), WeightFunction(f), PlotOptions::Prefix("tMC_Category"+std::to_string(counter) ) ); auto tEndIntegral2 = std::chrono::high_resolution_clock::now(); double t2 = std::chrono::duration( tEndIntegral2 - tStartIntegral2 ).count(); INFO( "Time for plots = " << t2 ); @@ -146,7 +145,7 @@ FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& counter++; } ); } - Chi2Estimator chi2( data, mc, pdf, 15 ); + Chi2Estimator chi2( data, mc, pdf, MinEvents(15) ); fr->addChi2( chi2.chi2(), chi2.nBins() ); auto twall_end = std::chrono::high_resolution_clock::now(); @@ -279,7 +278,7 @@ int main( int argc, char* argv[] ) fr->writeToFile( logFile ); output->cd(); - auto plots = events.makeDefaultProjections( Prefix( "Data_" ), Bins( NBins ) ); + auto plots = events.makeDefaultProjections( PlotOptions::Prefix( "Data_" ), PlotOptions::Bins( NBins ) ); for ( auto& plot : plots ) plot->Write(); output->Write(); diff --git a/apps/Generator.cpp b/apps/Generator.cpp index fd7ac128e78..89bbb6d2cba 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -160,13 +160,13 @@ int main( int argc, char** argv ) if( accepted.size() == 0 ) return -1; TFile* f = TFile::Open( outfile.c_str(), "RECREATE" ); accepted.tree( "DalitzEventList" )->Write(); - auto plots = accepted.makeDefaultProjections(Bins(nBins), LineColor(kBlack)); + auto plots = accepted.makeDefaultProjections(PlotOptions::Bins(nBins), PlotOptions::LineColor(kBlack)); for ( auto& plot : plots ) plot->Write(); if( NamedParameter("plots_2d",true) == true ){ auto proj = eventType.defaultProjections(nBins); for( size_t i = 0 ; i < proj.size(); ++i ){ for( size_t j = i+1 ; j < proj.size(); ++j ){ - accepted.makeProjection( Projection2D(proj[i], proj[j]), LineColor(kBlack) )->Write(); + accepted.makeProjection( Projection2D(proj[i], proj[j]), PlotOptions::LineColor(kBlack) )->Write(); } } } diff --git a/examples/FitterWithPolarisation.cpp b/examples/FitterWithPolarisation.cpp index 05aa87beadc..8ee80173425 100644 --- a/examples/FitterWithPolarisation.cpp +++ b/examples/FitterWithPolarisation.cpp @@ -112,15 +112,17 @@ int main( int argc, char* argv[] ) fit results + covariance matrix) of the fit result, and write them to a file. */ auto fitFractions = sig.fitFractions( fr->getErrorPropagator() ); - + + INFO("Adding fraction to file..."); fr->addFractions( fitFractions ); + INFO("Writing file ... "); fr->writeToFile( logFile ); output->cd(); /* Write out the data plots. This also shows the first example of the named arguments to functions, emulating python's behaviour in this area */ - auto plots = events.makeDefaultProjections(Prefix("Data"), Bins(100)); + auto plots = events.makeDefaultProjections(PlotOptions::Prefix("Data"), PlotOptions::Bins(100)); for ( auto& plot : plots ) plot->Write(); output->Close(); @@ -143,21 +145,21 @@ FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& /* Make the plots for the different components in the PDF, i.e. the signal and backgrounds. The structure assumed the PDF is some SumPDF. */ - unsigned int counter = 1; - for_each(pdf.pdfs(), [&]( auto& f ){ - auto mc_plot3 = mc.makeDefaultProjections(WeightFunction(f), Prefix("Model_cat"+std::to_string(counter))); - for( auto& plot : mc_plot3 ) - { - plot->Scale( ( data.integral() * f.getWeight() ) / plot->Integral() ); - plot->Write(); - } - counter++; - } ); +// unsigned int counter = 1; +// for_each(pdf.pdfs(), [&]( const auto& f ){ +// auto mc_plot3 = mc.makeDefaultProjections(WeightFunction(f.evaluator()), Prefix("Model_cat"+std::to_string(counter))); +// for( auto& plot : mc_plot3 ) +// { +// plot->Scale( ( data.integral() * f.getWeight() ) / plot->Integral() ); +// plot->Write(); +// } +// counter++; +// } ); /* Estimate the chi2 using an adaptive / decision tree based binning, down to a minimum bin population of 15, and add it to the output. */ - Chi2Estimator chi2( data, mc, pdf, 15 ); - chi2.writeBinningToFile("chi2_binning.txt"); - fr->addChi2( chi2.chi2(), chi2.nBins() ); + // Chi2Estimator chi2( data, mc, pdf, 15 ); + // chi2.writeBinningToFile("chi2_binning.txt"); + // fr->addChi2( chi2.chi2(), chi2.nBins() ); auto twall_end = std::chrono::high_resolution_clock::now(); double time_cpu = ( std::clock() - time ) / (double)CLOCKS_PER_SEC; diff --git a/examples/SignalOnlyFitter.cpp b/examples/SignalOnlyFitter.cpp index e49d43f317b..ce4bc7d5ded 100644 --- a/examples/SignalOnlyFitter.cpp +++ b/examples/SignalOnlyFitter.cpp @@ -103,7 +103,7 @@ int main( int argc, char* argv[] ) /* Generate events to normalise the PDF with. This can also be loaded from a file, which will be the case when efficiency variations are included. Default number of normalisation events is 5 million. */ - EventList eventsMC = intFile == "" ? Generator<>(evtType, &rndm).generate(1e7) : EventList(intFile, evtType, GetGenPdf(true)); + EventList eventsMC = intFile == "" ? Generator<>(evtType, &rndm).generate(2e6) : EventList(intFile, evtType, GetGenPdf(true)); sig.setMC( eventsMC ); @@ -124,7 +124,7 @@ int main( int argc, char* argv[] ) /* Write out the data plots. This also shows the first example of the named arguments to functions, emulating python's behaviour in this area */ - auto plots = events.makeDefaultProjections(Prefix("Data"), Bins(100)); + auto plots = events.makeDefaultProjections(PlotOptions::Prefix("Data"), PlotOptions::Bins(100)); for ( auto& plot : plots ) plot->Write(); output->Close(); @@ -147,27 +147,28 @@ FitResult* doFit( likelihoodType&& likelihood, EventList& data, EventList& mc, M double tWall = std::chrono::duration( twall_end - time_wall ).count(); INFO( "Wall time = " << tWall / 1000. ); INFO( "CPU time = " << time_cpu ); - - /* Make the plots for the different components in the PDF, i.e. the signal and backgrounds. - The structure assumed the PDF is some SumPDF. */ - unsigned int counter = 1; - for_each(likelihood.pdfs(), [&](auto& pdf){ - auto pfx = Prefix("Model_cat"+std::to_string(counter)); - auto mc_plot3 = mc.makeDefaultProjections(WeightFunction(pdf), pfx); - for( auto& plot : mc_plot3 ) - { - plot->Scale( ( data.integral() * pdf.getWeight() ) / plot->Integral() ); - plot->Write(); - } - counter++; - }); - + /* Estimate the chi2 using an adaptive / decision tree based binning, down to a minimum bin population of 15, and add it to the output. */ - Chi2Estimator chi2( data, mc, likelihood, 15 ); + + Chi2Estimator chi2( data, mc, likelihood.evaluator(&mc), MinEvents(15), Dim(data.eventType().dof()) ); chi2.writeBinningToFile("chi2_binning.txt"); fr->addChi2( chi2.chi2(), chi2.nBins() ); - fr->print(); + + /* Make the plots for the different components in the PDF, i.e. the signal and backgrounds. + The structure assumed the PDF is some SumPDF. */ + auto evaluator = likelihood.componentEvaluator(&mc); + auto evaluator_per_component = std::get<0>( likelihood.pdfs() ).componentEvaluator(&mc); + auto projections = data.eventType().defaultProjections(100); + for( const auto& proj : projections ) + { + auto [components, total] = proj(mc, evaluator, PlotOptions::Norm(data.size() ) ); + for( const auto& component : components ) component->Write(); + total->Write(); + auto [signal_components, total_signal_component] = proj(mc, evaluator_per_component, PlotOptions::Norm(data.size()) ); + for( const auto& component : signal_components ) component->Write(); + total_signal_component->Write(); + } return fr; } diff --git a/examples/SimFit.cpp b/examples/SimFit.cpp index dcc7b5b69ac..2671093485c 100644 --- a/examples/SimFit.cpp +++ b/examples/SimFit.cpp @@ -84,12 +84,12 @@ int main(int argc , char* argv[] ){ for( size_t i = 0 ; i < data.size(); ++i ) { INFO("Making figures for sample: " << i << " ..."); - auto dataPlots = data[i].makeDefaultProjections( Prefix("Data_"+std::to_string(i))); + auto dataPlots = data[i].makeDefaultProjections( PlotOptions::Prefix("Data_"+std::to_string(i))); for( auto& p : dataPlots ) p->Write(); size_t counter = 0; for_each(pdfs[i].pdfs(), [&]( auto& f ){ auto mc_plots = mcs[i].makeDefaultProjections(WeightFunction(f), - Prefix("Model_sample_"+std::to_string(i)+"_cat"+std::to_string(counter))); + PlotOptions::Prefix("Model_sample_"+std::to_string(i)+"_cat"+std::to_string(counter))); for( auto& plot : mc_plots ) { plot->Scale( ( data[i].integral() * f.getWeight() ) / plot->Integral() ); diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index 01e1c2737e6..98b66bcd496 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -98,7 +98,7 @@ std::vector AmplitudeRules::rulesForDecay(const std::string& head, con return rt; } -std::map> AmplitudeRules::rules() +const std::map>& AmplitudeRules::rules() const { return m_rules; } diff --git a/src/BinDT.cpp b/src/BinDT.cpp index 911ab247989..e6c15149b0d 100644 --- a/src/BinDT.cpp +++ b/src/BinDT.cpp @@ -80,7 +80,7 @@ std::function( const Event& )> BinDT::makeDefaultFunctors() DEBUG( "Problem has 2 d.o.f.s -> using Dalitz coordinates" ); return []( const Event& evt ) -> std::vector { return {evt.s( 0, 1 ), evt.s( 1, 2 )}; }; } - ERROR( "No functors found for dim = " << m_dim ); + ERROR( "No default functors found for dim = " << m_dim ); return nullptr; } @@ -97,6 +97,10 @@ BinDT::BinDT( const ArgumentPack& args ) } } +BinDT::BinDT( const EventList& events, const ArgumentPack& args ) : BinDT(args) +{ + m_top = makeNodes(events); +} void BinDT::readFromStream( std::istream& stream ) { std::map>> nodes; @@ -363,3 +367,17 @@ void BinDT::Decision::visit( const std::function& visit_fun m_left->visit( visit_function ); m_right->visit( visit_function ); } + +std::shared_ptr BinDT::makeNodes( const EventList& events ) +{ + std::vector data( m_dim * events.size() ); + std::vector addresses( events.size() ); + size_t counter = 0; + for ( auto& evt : events ) { + auto val = m_functors( evt ); + for ( unsigned int i = 0; i < m_dim; ++i ) data[m_dim * counter + i] = val[i]; + addresses[counter] = &( data[m_dim * counter] ); + counter++; + } + return makeNodes( addresses ); +} diff --git a/src/Chi2Estimator.cpp b/src/Chi2Estimator.cpp index 58047ad5c4c..500210f0489 100644 --- a/src/Chi2Estimator.cpp +++ b/src/Chi2Estimator.cpp @@ -33,21 +33,6 @@ struct Moment { double var() { return N == 0 ? 0 : xx; } }; -Chi2Estimator::Chi2Estimator( const EventList& dataEvents, const EventList& mcEvents, - const std::function& fcn, const unsigned int& minEvents ) : - m_binning( dataEvents, MinEvents( minEvents ), Dim( dataEvents.eventType().dof() ) ) -{ - doChi2( dataEvents, mcEvents, fcn ); -} - -Chi2Estimator::Chi2Estimator( const EventList& dataEvents, const EventList& mcEvents, - const std::function& fcn, const std::string& filename ) : - m_binning( File( filename ) ) -{ - doChi2( dataEvents, mcEvents, fcn ); -} - - double Chi2Estimator::chi2() const { return m_chi2; } double Chi2Estimator::nBins() const { return m_nBins; } void Chi2Estimator::writeBinningToFile( const std::string& filename ) { m_binning.serialize( filename ); } @@ -90,3 +75,5 @@ void Chi2Estimator::doChi2( const EventList& dataEvents, const EventList& mcEv m_nBins = m_binning.size(); } + + diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index e72d0ac3381..3bc4b612121 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -103,7 +103,6 @@ void CoherentSum::prepare() void CoherentSum::updateNorms( const std::vector& changedPdfIndices ) { - //for ( auto& i : changedPdfIndices ) m_integrator.prepareExpression( m_matrixElements[i].amp ); std::vector cacheIndex; std::transform( m_matrixElements.begin(), m_matrixElements.end(), std::back_inserter(cacheIndex), [this](auto& m){ return this->m_integrator.getCacheIndex( m.amp ) ; } ); @@ -282,7 +281,7 @@ void CoherentSum::reset( bool resetEvents ) for ( auto& mE : m_matrixElements ) mE.addressData = 999; if ( resetEvents ){ m_events = nullptr; - m_integrator = integrator(); + m_integrator = Integrator2(); } } @@ -297,7 +296,7 @@ void CoherentSum::setMC( EventList& sim ) { if ( m_verbosity ) INFO( "Setting norm. event list with:" << sim.size() << " events for " << this ); reset(); - m_integrator = integrator(&sim); + m_integrator = Integrator2(&sim); } real_t CoherentSum::norm() const @@ -368,3 +367,53 @@ complex_t CoherentSum::getVal( const Event& evt, const std::vector& cach value += m_matrixElements[i].coefficient * evt.getCache( cacheAddresses[i] ); return value; } + +std::function CoherentSum::evaluator(const EventList* events) const +{ + if( events != nullptr && events != &this->m_integrator.events() ) + ERROR("Evaluator only working on the integration sample, fix me!"); + std::vector address_mapping( size() ); + for( const auto& me : m_matrixElements ) address_mapping[me.addressData] = m_integrator.getCacheIndex( me.amp ); + std::vector values( m_integrator.events().size() ); + #ifdef _OPENMP + #pragma omp parallel for + #endif + for( unsigned int i = 0 ; i != m_integrator.events().size(); ++i ) + { + complex_t amp = 0; + for( unsigned j = 0 ; j != address_mapping.size(); ++j ) amp += m_matrixElements[j].coefficient * this->m_integrator.get(address_mapping[j], i); + values[i] = m_weight * std::norm(amp) / m_norm; + } + return arrayToFunctor(values, events); +} + +KeyedView CoherentSum::componentEvaluator(const EventList* events) const +{ + if( events != nullptr && events != &this->m_integrator.events() ) + ERROR("Evaluator only working on the integration sample, fix me!"); + + KeyedView rt(*events, m_matrixElements.size() ); + std::vector address_mapping(m_matrixElements.size()); + for( unsigned i = 0; i != m_matrixElements.size(); ++i ) address_mapping[i] = m_integrator.getCacheIndex( m_matrixElements[i].amp ); + + for( unsigned i = 0 ; i != m_matrixElements.size(); ++i ) + { + auto& me = m_matrixElements[i]; + rt.setKey(i, programatic_name( me.decayTree.decayDescriptor() ) ); + #ifdef _OPENMP + #pragma omp parallel for + #endif + for( unsigned evt = 0 ; evt != m_integrator.events().size(); ++evt ) + { + complex_t total = 0; + for( unsigned j = 0 ; j != m_matrixElements.size(); ++j ){ + total += this->m_integrator.get( address_mapping[i], evt ) * m_matrixElements[i].coefficient + * std::conj( this->m_integrator.get( address_mapping[j], evt ) * m_matrixElements[j].coefficient ); + } + + rt(events->at(evt), i) = m_weight * std::real( total ) / m_norm; + } + } + return rt; +} + diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index eb680b55b17..e5a1de4071e 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -87,7 +87,7 @@ void CompiledExpressionBase::to_stream( std::ostream& stream ) const stream << "extern \"C\" const char* " << progName() << "_name() { return \"" << m_name << "\"; } \n"; bool enable_cuda = NamedParameter("UseCUDA",false); size_t sizeOfStream = 0; - if( m_rto ) + if( use_rto() ) { stream << "extern \"C\" " << returnTypename() << " " << progName() << "(" << fcnSignature() << "){\n"; addDependentExpressions( stream , sizeOfStream ); diff --git a/src/Event.cpp b/src/Event.cpp index 8ca8c171466..6ffa95df0b5 100644 --- a/src/Event.cpp +++ b/src/Event.cpp @@ -1,4 +1,4 @@ -#include + #include #include #include diff --git a/src/EventList.cpp b/src/EventList.cpp index 5068ba0d1b4..c7b90bdd5c5 100644 --- a/src/EventList.cpp +++ b/src/EventList.cpp @@ -118,7 +118,7 @@ void EventList::loadFromTree( TTree* tree, const ArgumentPack& args ) INFO("Time to read tree = " << read_time << "[ms]; nEntries = " << size() ); } -TTree* EventList::tree( const std::string& name, const std::vector& extraBranches ) +TTree* EventList::tree( const std::string& name, const std::vector& extraBranches ) const { std::string title = m_eventType.mother(); for( unsigned i = 0 ; i != m_eventType.size(); ++i ) title += " " + m_eventType[i]; @@ -131,16 +131,13 @@ TTree* EventList::tree( const std::string& name, const std::vector& double genPdf = 1; double weight = 1; auto format = m_eventType.getEventFormat( true ); - - for ( auto& f : format ){ - outputTree->Branch( f.first.c_str(), tmp.address( f.second ) ); - } - for ( auto& f : m_extensions ){ - outputTree->Branch( f.first.c_str(), tmp.address( f.second ) ); - } + + for ( const auto& f : format ) outputTree->Branch( f.first.c_str(), tmp.address( f.second ) ); + for ( const auto& f : m_extensions ) outputTree->Branch( f.first.c_str(), tmp.address( f.second ) ); + outputTree->Branch( "genPdf", &genPdf ); outputTree->Branch( "weight", &weight ); - for ( auto& evt : *this ) { + for ( const auto& evt : *this ) { tmp = evt; genPdf = evt.genPdf(); weight = evt.weight(); @@ -152,21 +149,17 @@ TTree* EventList::tree( const std::string& name, const std::vector& std::vector EventList::makeProjections( const std::vector& projections, const ArgumentPack& args ) { std::vector plots; - for ( auto& proj : projections ) { - TH1D* plot = makeProjection(proj, args ); - DEBUG("Made plot ... " << plot->GetName() ); - plots.push_back( plot ); - } + for ( const auto& proj : projections ) plots.push_back( makeProjection(proj, args) ); return plots; } TH1D* EventList::makeProjection( const Projection& projection, const ArgumentPack& args ) const { - auto selection = args.getArg().val; + auto selection = args.getArg().val; auto weightFunction = args.getArg().val; - std::string prefix = args.getArg(std::string("")); + std::string prefix = args.getArg(std::string("")); auto plot = projection.plot(prefix); - plot->SetLineColor(args.getArg(kBlack).val); + plot->SetLineColor(args.getArg(kBlack).val); plot->SetMarkerSize(0); for( auto& evt : m_data ){ if( selection != nullptr && !selection(evt) ) continue; @@ -179,9 +172,9 @@ TH1D* EventList::makeProjection( const Projection& projection, const ArgumentPac TH2D* EventList::makeProjection( const Projection2D& projection, const ArgumentPack& args ) const { - auto selection = args.getArg().val; + auto selection = args.getArg().val; auto weightFunction = args.getArg().val; - std::string prefix = args.getArg().val; + std::string prefix = args.getArg().val; auto plot = projection.plot(prefix); for ( auto& evt : m_data ){ if ( selection != nullptr && !selection(evt) ) continue; @@ -228,12 +221,9 @@ void EventList::resetCache() double EventList::integral() const { - double integral = 0; - for ( auto& evt : *this ) { - integral += evt.weight(); - } - return integral; + return std::accumulate( std::begin(*this), std::end(*this), 0, [](double rv, const auto& evt){ return rv + evt.weight(); } ); } + void EventList::add( const EventList& evts ) { resetCache(); @@ -243,16 +233,6 @@ void EventList::add( const EventList& evts ) rbegin()->resizeCache( 0 ); } } -double EventList::norm() -{ - if ( m_norm == 0 ) { - double totalWeight = 0; -#pragma omp parallel for reduction( + : totalWeight ) - for ( unsigned int i = 0; i < size(); ++i ) totalWeight += ( *this )[i].weight() / ( *this )[i].genPdf(); - m_norm = totalWeight; - } - return m_norm; -} void EventList::clear() { @@ -260,7 +240,7 @@ void EventList::clear() } void EventList::erase(const std::vector::iterator& begin, - const std::vector::iterator& end) + const std::vector::iterator& end) { m_data.erase( begin, end ); } diff --git a/src/FitFraction.cpp b/src/FitFraction.cpp index 65a1cec41bf..f064e2d7750 100644 --- a/src/FitFraction.cpp +++ b/src/FitFraction.cpp @@ -19,8 +19,6 @@ FitFraction::FitFraction( const std::string& line ) m_error = stod( tokens[3] ); } -std::shared_ptr FitFraction::particle() const { return std::make_shared( m_name ); } - FitFraction::FitFraction( const std::string& name, const double& frac, const double& err ) : m_name( name ), m_value( frac ), m_error( err ) { diff --git a/src/Integrator2.cpp b/src/Integrator2.cpp index dacc4902bb4..c36df07a789 100644 --- a/src/Integrator2.cpp +++ b/src/Integrator2.cpp @@ -13,16 +13,17 @@ void Integrator2::integrateBlock() addr_i[roll] = m_integrals[roll].i; addr_j[roll] = m_integrals[roll].j; } -#pragma omp parallel for reduction(+: re, im) - for ( size_t i = 0; i < m_events->size(); ++i ) { - for ( size_t roll = 0; roll < N; ++roll ) { - auto c = m_buffer[addr_i[roll]][i] * std::conj(m_buffer[addr_j[roll]][i]); + for ( size_t roll = 0; roll < N; ++roll ) { + auto& b1 = m_buffer[m_integrals[roll].i]; + auto& b2 = m_buffer[m_integrals[roll].j]; + #pragma omp parallel for reduction(+: re, im) + for ( size_t i = 0; i < m_events->size(); ++i ) { + auto c = b1[i] * std::conj(b2[i]); re[roll] += m_weight[i] * std::real(c); im[roll] += m_weight[i] * std::imag(c); } } - for ( size_t j = 0; j < m_counter; ++j ) - m_integrals[j].transfer( complex_t( re[j], im[j] ) / m_norm ); + for ( size_t j = 0; j < m_counter; ++j ) m_integrals[j].transfer( complex_t( re[j], im[j] ) / m_norm ); m_counter = 0; } diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index c4ac3ab2a7a..e63ab654231 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -33,9 +33,7 @@ using namespace AmpGen; using namespace std::complex_literals; -namespace AmpGen { - make_enum(spaceType, spin, flavour) -} +namespace AmpGen { make_enum(spaceType, spin, flavour) } PolarisedSum::PolarisedSum(const EventType& type, MinuitParameterSet& mps, @@ -48,8 +46,8 @@ PolarisedSum::PolarisedSum(const EventType& type, , m_rules (mps) , m_dim (m_eventType.dim()) { - std::string objCache = NamedParameter("PolarisedSum::ObjectCache","" ); - spaceType stype = NamedParameter("PolarisedSum::SpaceType", spaceType::spin); + std::string objCache = NamedParameter("PolarisedSum::ObjectCache", "" ); + spaceType stype = NamedParameter( "PolarisedSum::SpaceType" , spaceType::spin); if( stype == spaceType::spin ) { auto prodPols = polarisations(m_eventType.mother()); @@ -73,13 +71,13 @@ PolarisedSum::PolarisedSum(const EventType& type, p.setPolarisationState( polStates[j] ); thisExpression[j] = make_cse( p.getExpression(&syms) ); } - m_matrixElements[i] = TransitionMatrix>( + m_matrixElements[i] = TransitionMatrix( p, coupling, - CompiledExpression< std::vector,const real_t*, const real_t*>( + CompiledExpression( TensorExpression(thisExpression), p.decayDescriptor(), - this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,this->m_mps ) ); + this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,this->m_mps ) ); CompilerWrapper().compile( m_matrixElements[i].amp ); }); } @@ -99,10 +97,10 @@ PolarisedSum::PolarisedSum(const EventType& type, auto& tm = i < r1.size() ? r1[i] : r2[i-r1.size()]; thisExpression[0] = i < r1.size() ? make_cse( tm.first.getExpression(&syms) ) : 0; thisExpression[1] = i < r1.size() ? 0 : make_cse( tm.first.getExpression(&syms) ); - m_matrixElements[i] = TransitionMatrix>( + m_matrixElements[i] = TransitionMatrix( tm.first, tm.second, - CompiledExpression< std::vector,const real_t*, const real_t*>( + CompiledExpression( TensorExpression(thisExpression), tm.first.decayDescriptor(), this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,this->m_mps ) ); @@ -181,7 +179,7 @@ std::vector convertProxies(const std::vector& proxyVect return rt; } -std::vector>> PolarisedSum::matrixElements() const +std::vector> PolarisedSum::matrixElements() const { return m_matrixElements; } @@ -190,24 +188,19 @@ void PolarisedSum::prepare() { DEBUG( "Preparing: " << m_prefix << " " << m_events << " ready = " << m_integrator.isReady() ); transferParameters(); - std::vector hasChanged( m_matrixElements.size(), false); size_t nChanges = 0; ProfileClock tEval; size_t size_of = size() / m_matrixElements.size(); if( m_events != nullptr ) m_events->reserveCache( size() ); - if( m_integrator.isReady() ) m_integrator.events().reserveCache( size() ); - for( size_t i = 0; i < m_matrixElements.size(); ++i ){ - ProfileClock tMEval; - auto& t = m_matrixElements[i]; + if( m_integrator.isReady() ) m_integrator.reserveCache( size() ); + for(auto& t : m_matrixElements){ if( m_nCalls != 0 && !t.amp.hasExternalsChanged() ) continue; - if( t.addressData == 999 ) t.addressData = m_events->registerExpression(t.amp, m_dim.first * m_dim.second ); m_events->updateCache(t.amp, t.addressData); m_integrator.prepareExpression(t.amp, size_of); - tMEval.stop(); t.amp.resetExternals(); - hasChanged[i] = true; + t.workToDo = true; nChanges++; - if( m_nCalls == 0 && m_integrator.isReady() ) m_integIndex.push_back( m_integrator.events().getCacheIndex( t.amp ) ); + if( m_nCalls == 0 && m_integrator.isReady() ) m_integIndex.push_back( m_integrator.getCacheIndex( t.amp ) ); } if( !m_probExpression.isLinked() ) build_probunnormalised(); tEval.stop(); @@ -215,46 +208,52 @@ void PolarisedSum::prepare() m_rho = densityMatrix(m_dim.first, m_pVector); if( m_integrator.isReady() ) { - if(nChanges != 0) calculateNorms(hasChanged); + if(nChanges != 0) calculateNorms(); complex_t z = 0; for(size_t i = 0; i < m_matrixElements.size(); ++i){ - for(size_t j = i; j < m_matrixElements.size(); ++j){ - z += ((i==j) ? 1. : 2. ) * m_matrixElements[i].coupling()*std::conj(m_matrixElements[j].coupling())*norm(i,j); + for(size_t j = 0; j < m_matrixElements.size(); ++j){ + // z += ((i==j) ? 1. : 2. ) * m_matrixElements[i].coupling()*std::conj(m_matrixElements[j].coupling())*norm(i,j); + z += m_matrixElements[i].coupling()*std::conj(m_matrixElements[j].coupling())* ( i > j ? std::conj(norm(j,i)) : norm(i,j) ); } } m_norm = std::real(z); if(m_nCalls % 10000 == 0 && m_prefix == "") debug_norm(); } + tIntegral.stop(); if(m_verbosity && nChanges != 0) INFO("Time to evaluate = " << tEval << " ms; " << "norm = " << tIntegral << " ms; " << "pdfs = " << nChanges); m_nCalls++; + for( auto& me : m_matrixElements ) me.workToDo = false; } void PolarisedSum::debug_norm() { double norm_slow = 0; for( auto& evt : m_integrator.events() ) - norm_slow += evt.weight() * prob_unnormalised(evt) / evt.genPdf(); + norm_slow += evt.weight() * getValNoCache(evt) / evt.genPdf(); auto evt = m_integrator.events()[0]; INFO("Event[0]: " << prob_unnormalised(evt) << " " << getValNoCache(evt) ); INFO("Norm : " << std::setprecision(10) << "bilinears=" << m_norm - << "; exact=" << norm_slow / m_integrator.sampleNorm() - << "; d = " << m_norm - norm_slow / m_integrator.sampleNorm() - << "; sample=" << m_integrator.sampleNorm() ); + << "; exact=" << norm_slow / m_integrator.norm() + << "; d = " << m_norm - norm_slow / m_integrator.norm() + << "; sample=" << m_integrator.norm() ); } void PolarisedSum::setEvents( EventList& events ) { reset(); m_events = &events; + for( unsigned i = 0; i != m_matrixElements.size(); ++i ) + m_matrixElements[i].addressData = m_events->registerExpression(m_matrixElements[i].amp, m_dim.first * m_dim.second ); } void PolarisedSum::setMC( EventList& events ) { m_nCalls = 0; m_integrator = integrator(&events); + } size_t PolarisedSum::size() const @@ -289,7 +288,7 @@ Tensor PolarisedSum::transitionMatrix() return T_matrix; } -double PolarisedSum::prob_unnormalised( const Event& evt ) const +real_t PolarisedSum::prob_unnormalised( const Event& evt ) const { return m_probExpression( evt.getCachePtr(0) ); } @@ -316,11 +315,11 @@ complex_t PolarisedSum::norm(const size_t& i, const size_t& j, PolarisedSum::int return total; } -void PolarisedSum::calculateNorms(const std::vector& hasChanged) +void PolarisedSum::calculateNorms() { for( unsigned i = 0 ; i < m_matrixElements.size(); ++i ){ for( unsigned j = i; j < m_matrixElements.size(); ++j ){ - if( hasChanged[i] || hasChanged[j] ) norm(i, j, &m_integrator); + if( m_matrixElements[i].workToDo || m_matrixElements[j].workToDo ) norm(i, j, &m_integrator); } } m_integrator.flush(); @@ -366,14 +365,16 @@ void PolarisedSum::generateSourceCode(const std::string& fname, const double& no Expression event = Parameter("x0",0,true); std::vector expressions(size); for( auto& p : m_matrixElements ){ - p.amp.prepare(); - p.amp.to_stream( stream ); - p.amp.compileWithParameters( stream ); + auto expr = CompiledExpression, const real_t*, const real_t*>( + p.amp.expression(), + p.decayDescriptor(), + m_eventType.getEventFormat(), DebugSymbols() ,m_mps ) ; + expr.prepare(); + expr.to_stream( stream ); + expr.compileWithParameters( stream ); Array z( make_cse( Function( programatic_name( p.amp.name()) + "_wParams", {event} ) ), size ); INFO( p.decayDescriptor() << " coupling = " << p.coupling() ); - for( unsigned int j = 0 ; j < size; ++j ){ - expressions[j] = expressions[j] + p.coupling() * z[j]; - } + for( unsigned int j = 0 ; j < size; ++j ) expressions[j] = expressions[j] + p.coupling() * z[j]; } Tensor T_matrix( expressions, {m_dim.first, m_dim.second} ); T_matrix.st(); @@ -430,11 +431,12 @@ Expression PolarisedSum::probExpression(const Tensor& T_matrix, const std::vecto std::vector PolarisedSum::fitFractions(const LinearErrorPropagator& prop) { bool recomputeIntegrals = NamedParameter("PolarisedSum::RecomputeIntegrals", false ); + bool interferenceFractions = NamedParameter("PolarisedSum::InterferenceFractions", false ); std::vector outputFractions; - for(auto& rule : m_rules.rules()) + for(const auto& rule : m_rules.rules()) { FitFractionCalculator pCalc(this, findIndices(m_matrixElements, rule.first), recomputeIntegrals); - for(auto& process : rule.second) + for(const auto& process : rule.second) { if(process.head() == m_eventType.mother() && process.prefix() != m_prefix) continue; auto numeratorIndices = processIndex(m_matrixElements, process.name()); @@ -443,26 +445,33 @@ std::vector PolarisedSum::fitFractions(const LinearErrorPropagator& } if( pCalc.calculators.size() == 0 ) continue; auto fractions = pCalc(rule.first, prop); - for( auto& f : fractions ) outputFractions.emplace_back(f); + for( const auto& f : fractions ) outputFractions.emplace_back(f); } - auto head_rules = m_rules.rulesForDecay(m_eventType.mother(), m_prefix); - FitFractionCalculator iCalc(this, findIndices(m_matrixElements, m_eventType.mother()), recomputeIntegrals); - for(size_t i = 0 ; i < head_rules.size(); ++i) + INFO("Fit fractions: "); + for(const auto& p : outputFractions) INFO(p); + + if( interferenceFractions ) { - auto process_i = head_rules[i]; - auto num_i = processIndex(m_matrixElements, process_i.name()); - if( num_i.size() == 0 || num_i == iCalc.normSet ) continue; - for( size_t j = i+1 ; j < head_rules.size(); ++j ){ - auto process_j = head_rules[j]; - auto num_j = processIndex(m_matrixElements, process_j.name()); - if( num_j.size() == 0 || num_j == iCalc.normSet ) continue; - iCalc.emplace_back(process_i.name() + " " + process_j.name() , num_i, num_j); + + auto head_rules = m_rules.rulesForDecay(m_eventType.mother(), m_prefix); + FitFractionCalculator iCalc(this, findIndices(m_matrixElements, m_eventType.mother()), recomputeIntegrals); + for(size_t i = 0 ; i < head_rules.size(); ++i) + { + auto process_i = head_rules[i]; + auto num_i = processIndex(m_matrixElements, process_i.name()); + if( num_i.size() == 0 || num_i == iCalc.normSet ) continue; + for( size_t j = i+1 ; j < head_rules.size(); ++j ){ + auto process_j = head_rules[j]; + auto num_j = processIndex(m_matrixElements, process_j.name()); + if( num_j.size() == 0 || num_j == iCalc.normSet ) continue; + iCalc.emplace_back(process_i.name() + " " + process_j.name() , num_i, num_j); + } } + auto ifractions = iCalc(m_eventType.mother(), prop); + INFO("Interference fractions: "); + for( auto& f : ifractions ) INFO( FitFraction(f) ); } - auto ifractions = iCalc(m_eventType.mother(), prop); - for(auto& p : outputFractions) INFO(p); - INFO("INTERFERENCE FRACTIONS"); - for( auto& f : ifractions ) INFO( FitFraction(f) ); + INFO("Returning: " << outputFractions.size() << " fractions"); return outputFractions; } @@ -491,3 +500,64 @@ real_t PolarisedSum::getValNoCache( const Event& evt ) void PolarisedSum::setWeight( MinuitProxy param ){ m_weight = param; } double PolarisedSum::getWeight() const { return m_weight ; } + +std::function PolarisedSum::evaluator(const EventList* events) const +{ + if( events != nullptr && events != &this->m_integrator.events() ) + ERROR("Evaluator only working on the integration sample, fix me!"); + + std::vector address_mapping( size() ); + for( const auto& me : m_matrixElements ){ + for( unsigned i = 0; i != size() / m_matrixElements.size(); ++i ) + address_mapping[me.addressData+i] = m_integrator.getCacheIndex( me.amp ) + i; + } + std::vector values( m_integrator.events().size() ); + std::vector buffer(address_mapping.size()); + #ifdef _OPENMP + #pragma omp parallel for firstprivate(buffer) + #endif + for( unsigned int i = 0 ; i != m_integrator.events().size(); ++i ) + { + for( unsigned j = 0 ; j != address_mapping.size(); ++j ) buffer[j] = this->m_integrator.get(address_mapping[j], i); + values[i] = m_weight * m_probExpression(&buffer[0]) / m_norm; + } + return arrayToFunctor(values, events); +} + +KeyedView PolarisedSum::componentEvaluator(const EventList* events) const +{ + if( events != nullptr && events != &this->m_integrator.events() ) + ERROR("Evaluator only working on the integration sample, fix me!"); + KeyedView rt(*events, m_matrixElements.size() ); + std::vector address_mapping(m_matrixElements.size()); + for( unsigned i = 0; i != m_matrixElements.size(); ++i ) + address_mapping[i] = m_integrator.getCacheIndex( m_matrixElements[i].amp ); + + for( unsigned i = 0 ; i != m_matrixElements.size(); ++i ) + { + auto& me = m_matrixElements[i]; + rt.setKey(i, programatic_name( me.decayTree.decayDescriptor() ) ); + #ifdef _OPENMP + #pragma omp parallel for + #endif + for( unsigned evt = 0 ; evt != m_integrator.events().size(); ++evt ) + { + complex_t total = 0; + for( unsigned j = 0 ; j != m_matrixElements.size(); ++j ){ + for( unsigned x = 0; x != m_norms.size(); ++x ) + { + auto s1 = m_dim.first; + auto s2 = m_dim.second; + auto f = x % s2; + auto psiIndex = (x-f) / s2; + auto m2 = psiIndex % s1; + auto m1 = (psiIndex-m2)/s1; + total += m_rho[psiIndex] * this->m_integrator.get( address_mapping[i] + m1 * s2 + f, evt ) * m_matrixElements[i].coefficient + * std::conj( this->m_integrator.get( address_mapping[j] + m2 * s2 + f, evt ) * m_matrixElements[j].coefficient ); + } + } + rt(events->at(evt), i) = m_weight * std::real( total ) / m_norm; + } + } + return rt; +} diff --git a/src/Projection.cpp b/src/Projection.cpp index aacf9ea405b..1a16dbbd1b6 100644 --- a/src/Projection.cpp +++ b/src/Projection.cpp @@ -7,8 +7,10 @@ #include "TAxis.h" #include "TH1.h" #include "TH2.h" +#include "THStack.h" using namespace AmpGen; +using namespace AmpGen::PlotOptions; Projection::Projection() = default; @@ -44,10 +46,8 @@ TH1D* Projection::plot(const std::string& prefix) const { plot->SetMinimum(0); return plot; } -std::function Projection::binFunctor() const { - return [this](auto& evt){ - - return int ( ( (*this)(evt) - m_min ) / m_width ) ; }; +std::function Projection::binFunctor() const { + return [this](auto& evt){ return int ( ( (*this)(evt) - m_min ) / m_width ) ;}; } TH2D* Projection2D::plot(const std::string& prefix) const { @@ -74,3 +74,30 @@ TH1D* Projection::projInternal( const EventList& events, const ArgumentPack& arg { return events.makeProjection(*this, args); } + +std::tuple, THStack*> Projection::projInternal(const EventList& events, const KeyedView& weightFunction, const ArgumentPack& args) const +{ +// INFO("Making projection: " << m_name << " classes = " << weightFunction.width() << " " << &(events[0]) ); + std::vector hists; + double norm_sum = args.getArg(1).val; + std::string prefix = args.getArg().val; + THStack* stack = args.getArg(new THStack()).val; + if( prefix != "" ) prefix = prefix +"_"; + for( unsigned int i = 0 ; i != weightFunction.width(); ++i ) + hists.push_back( plot(prefix + weightFunction.key(i)==""?"C"+std::to_string(i):weightFunction.key(i)) ); + auto selection = args.getArg().val; + for( const auto& evt : events ){ + if( selection != nullptr && !selection(evt) ) continue; + auto pos = operator()(evt); + auto weights = weightFunction(evt); + for( unsigned j = 0 ; j != weightFunction.width(); ++j ) hists[j]->Fill( pos, evt.weight() * weights[j] / evt.genPdf() ); + } + std::sort( std::begin(hists), std::end(hists), [](auto& h1, auto& h2){ return h1->Integral() < h2->Integral() ; } ); + double total = std::accumulate( std::begin(hists), std::end(hists), 0.0, [](double& t, auto& h){ return t + h->Integral() ; } ); + if( total == 0 ) ERROR("Norm = " << total ); + else for( auto& h : hists ) h->Scale( norm_sum / total ); + stack->SetName( (prefix + name() + "_stack").c_str()); + for( auto& h : hists ) stack->Add(h, "C HIST"); + return {hists, stack}; +} + From 65952768e1b0f064d6a37be77cd7cb9039879d2c Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 9 Apr 2020 17:33:41 +0200 Subject: [PATCH 163/250] Begin vectorising the code --- AmpGen/ASTResolver.h | 7 +- AmpGen/AmplitudeRules.h | 32 ++- AmpGen/ArgumentPack.h | 20 +- AmpGen/BinDT.h | 26 ++- AmpGen/CoherentSum.h | 51 +++-- AmpGen/CompiledExpression.h | 395 ++++++++++++++++---------------- AmpGen/CompiledExpressionBase.h | 16 +- AmpGen/CompilerWrapper.h | 1 + AmpGen/DynamicFCN.h | 5 +- AmpGen/Event.h | 39 ++-- AmpGen/EventList.h | 55 ++--- AmpGen/EventListSIMD.h | 173 ++++++++++++++ AmpGen/Expression.h | 5 + AmpGen/Generator.h | 25 +- AmpGen/Integrator.h | 287 ++++++----------------- AmpGen/Integrator2.h | 84 ------- AmpGen/IntegratorSIMD.h | 73 ++++++ AmpGen/LiteSpan.h | 12 +- AmpGen/PhaseSpace.h | 2 +- AmpGen/Plots.h | 104 --------- AmpGen/PolarisedSum.h | 22 +- AmpGen/ProfileClock.h | 24 +- AmpGen/Projection.h | 15 +- AmpGen/RecursivePhaseSpace.h | 2 +- AmpGen/SumPDF.h | 45 +++- AmpGen/ThreeBodyCalculators.h | 6 +- AmpGen/TreePhaseSpace.h | 4 +- AmpGen/Utilities.h | 9 +- Standalone.cmake | 12 +- apps/ConvertToSourceCode.cpp | 10 +- apps/Debugger.cpp | 8 +- apps/Fitter.cpp | 23 +- examples/QcGenerator.cpp | 4 +- examples/SignalOnlyFitter.cpp | 40 ++-- src/ASTResolver.cpp | 1 + src/BinDT.cpp | 18 +- src/Chi2Estimator.cpp | 5 +- src/CoherentSum.cpp | 171 +++++++------- src/CompiledExpressionBase.cpp | 6 +- src/CompilerWrapper.cpp | 15 +- src/Event.cpp | 19 +- src/EventList.cpp | 24 +- src/EventListSIMD.cpp | 303 ++++++++++++++++++++++++ src/Expression.cpp | 24 +- src/Generator.cpp | 2 +- src/IncoherentSum.cpp | 17 +- src/Integrator.cpp | 77 +++++++ src/Integrator2.cpp | 80 ------- src/IntegratorSIMD.cpp | 69 ++++++ src/Lineshapes.cpp | 31 ++- src/Lineshapes/kMatrix.cpp | 4 +- src/Minimiser.cpp | 2 +- src/Particle.cpp | 9 +- src/PhaseSpace.cpp | 4 +- src/Plots.cpp | 107 --------- src/PolarisedSum.cpp | 69 +++--- src/Projection.cpp | 48 +++- src/RecursivePhaseSpace.cpp | 8 +- src/ThreeBodyCalculators.cpp | 25 +- src/TreePhaseSpace.cpp | 8 +- src/UnaryExpression.cpp | 27 ++- test/test_phaseSpace.cpp | 2 +- 62 files changed, 1584 insertions(+), 1227 deletions(-) create mode 100644 AmpGen/EventListSIMD.h delete mode 100644 AmpGen/Integrator2.h create mode 100644 AmpGen/IntegratorSIMD.h delete mode 100644 AmpGen/Plots.h create mode 100644 src/EventListSIMD.cpp delete mode 100644 src/Integrator2.cpp create mode 100644 src/IntegratorSIMD.cpp delete mode 100644 src/Plots.cpp diff --git a/AmpGen/ASTResolver.h b/AmpGen/ASTResolver.h index fcfe3297fc0..aa978026649 100644 --- a/AmpGen/ASTResolver.h +++ b/AmpGen/ASTResolver.h @@ -43,7 +43,9 @@ namespace AmpGen { } size_t nParams() const { return m_nParameters ; } bool enableCuda() const { return m_enable_cuda ; } + bool enableAVX() const { return m_enable_avx; } bool enableCompileConstants() const { return m_enable_compileTimeConstants ;} + void setEnableAVX(){ m_enable_avx = true ; } std::map> cacheFunctions() const; void addResolvedParameter(const IExpression* param, const std::string& thing); void addResolvedParameter(const IExpression* param, const size_t& address, const size_t& arg=0); @@ -60,8 +62,9 @@ namespace AmpGen { const MinuitParameterSet* m_mps; /// Set of MinuitParameters std::map m_tempTrees; /// temporary store of sub-trees for performing cse reduction unsigned int m_nParameters; /// Number of parameters - bool m_enable_cuda; /// flag to generate CUDA code <> - bool m_enable_compileTimeConstants; /// flag to enable compile time constants <> + bool m_enable_cuda {false}; /// flag to generate CUDA code <> + bool m_enable_avx {false};/// flag to generate vectorised code <> + bool m_enable_compileTimeConstants {false}; /// flag to enable compile time constants <> }; template <> void ASTResolver::resolve( const Parameter& obj ); diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index 2dbb64ed0db..2c57d2e5689 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -14,6 +14,9 @@ #include "AmpGen/Event.h" #include "AmpGen/Particle.h" #include "AmpGen/ExpressionParser.h" +#if ENABLE_AVX2 + #include "AmpGen/EventListSIMD.h" +#endif namespace AmpGen { @@ -84,15 +87,20 @@ namespace AmpGen template struct TransitionMatrix { + #if ENABLE_AVX2 + using float_v = AVX2::float_t; + #else + using float_v = real_t; + #endif TransitionMatrix() = default; TransitionMatrix(const Particle& dt, const TotalCoupling& coupling, - const CompiledExpression & amp) : + const CompiledExpression & amp) : decayTree(dt), coupling(coupling), amp(amp) {} - TransitionMatrix(Particle& dt, + TransitionMatrix(const Particle& dt, const TotalCoupling& coupling, const MinuitParameterSet& mps, const std::map& evtFormat, @@ -100,17 +108,21 @@ namespace AmpGen decayTree(dt), coupling(coupling), amp(decayTree.getExpression(debugThis ? &db : nullptr ), decayTree.decayDescriptor(), evtFormat, db, &mps ) {} - - const RT operator()(const Event& event) const { return amp(event.address() ); } - const RT operator()(const Event& event, const size_t& cacheOffset) const { return amp(event.address() + cacheOffset); } + #if ENABLE_AVX2 + const RT operator()(const Event& event) const { return amp(EventListSIMD::makeEvent(event).data()); } + #else + const RT operator()(const Event& event) const { return amp(event.address()); } + #endif const std::string decayDescriptor() const { return decayTree.decayDescriptor() ; } + std::string name() const { return amp.name(); } + unsigned returnTypeSize() const { return amp.returnTypeSize(); } Particle decayTree; TotalCoupling coupling; complex_t coefficient; DebugSymbols db; - CompiledExpression amp; - size_t addressData = {999}; + CompiledExpression amp; + size_t addressData = {999}; }; template std::vector processIndex(const std::vector>& tm, const std::string& label) @@ -146,7 +158,7 @@ namespace AmpGen TransitionMatrix() = default; TransitionMatrix(const Particle& dt, const TotalCoupling& coupling, - const CompiledExpression & amp) : + const CompiledExpression & amp) : decayTree(dt), coupling(coupling), amp(amp) {} @@ -176,9 +188,11 @@ namespace AmpGen TotalCoupling coupling; complex_t coefficient; DebugSymbols db; - CompiledExpression amp; + CompiledExpression amp; size_t addressData = {999}; bool workToDo = {false}; + std::string name() const { return amp.name(); } + unsigned returnTypeSize() const { return amp.returnTypeSize(); } }; } // namespace AmpGen diff --git a/AmpGen/ArgumentPack.h b/AmpGen/ArgumentPack.h index c1decb23862..a9e745a7750 100644 --- a/AmpGen/ArgumentPack.h +++ b/AmpGen/ArgumentPack.h @@ -12,7 +12,7 @@ namespace AmpGen #define DECLARE_ARGUMENT(X, Y) \ struct X : public AmpGen::Argument { \ template \ - explicit X(Z val) : AmpGen::Argument(val){} \ + explicit X(Z val = Z()) : AmpGen::Argument(val){} \ X() : AmpGen::Argument(){} \ } /** @class IArgument @@ -76,14 +76,20 @@ namespace AmpGen std::tuple argTuple( args... ); for_each(argTuple, [this](const auto& f){ this->addArgument(f) ; } ); } - template - ARG getArg( const DEFAULT_TYPE& default_argument = DEFAULT_TYPE() ) const + template arg_type* get() const { - for ( auto param : m_parameters ) { - auto ptr = dynamic_cast( param.get() ); - if ( ptr != nullptr ) return *ptr; + for( const auto& param : m_parameters ) + { + auto ptr = dynamic_cast(param.get()); + if( ptr != nullptr ) return ptr; } - return ARG(default_argument); + return nullptr; + } + template + arg_type getArg( const default_arg_type& default_argument = default_arg_type() ) const + { + auto p = get(); + return p == nullptr ? arg_type(default_argument) : *p; } private: std::vector> m_parameters; diff --git a/AmpGen/BinDT.h b/AmpGen/BinDT.h index 5a29f25aefd..2201e8f36d2 100644 --- a/AmpGen/BinDT.h +++ b/AmpGen/BinDT.h @@ -89,9 +89,15 @@ namespace AmpGen { m_top = makeNodes( addr ); } - template BinDT( const EventList& events, const ARGS&... args ) : BinDT(ArgumentPack( args... ) ) + template BinDT( const EventList& events, const ARGS&... args ) : BinDT(ArgumentPack(args...) ) + { + m_top = makeNodes( events.begin(), events.end() ); + } + template BinDT( const iterator_type& begin, + const iterator_type& end, const ARGS&... args ) : BinDT(ArgumentPack( args... ) ) { - m_top = makeNodes( events ); + m_top = makeNodes(begin, end ); } explicit BinDT( const ArgumentPack& args ); BinDT( const EventList& events, const ArgumentPack& args ); @@ -114,7 +120,21 @@ namespace AmpGen std::function( const Event& )> makeDefaultFunctors(); void refreshQueue(const std::vector&, std::queue&, const unsigned&); - std::shared_ptr makeNodes(const EventList&); + template + std::shared_ptr makeNodes(const iterator_type& begin, const iterator_type& end) + { + std::vector data( m_dim * (end-begin) ); + std::vector addresses( end-begin ); + size_t counter = 0; + for ( auto evt = begin; evt != end; ++evt ) + { + auto val = m_functors( *evt ); + for ( unsigned int i = 0; i < m_dim; ++i ) data[m_dim * counter + i] = val[i]; + addresses[counter] = &( data[m_dim * counter] ); + counter++; + } + return makeNodes( addresses ); + } std::shared_ptr makeNodes(const std::vector&, std::queue, const unsigned&); std::shared_ptr makeNodes(const std::vector&); std::shared_ptr makeNodes(const std::vector&, const std::vector&); diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index 514c5d0d46f..41f8cdfa30d 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -13,14 +13,15 @@ #include "AmpGen/AmplitudeRules.h" #include "AmpGen/CompiledExpression.h" #include "AmpGen/EventList.h" +#include "AmpGen/EventListSIMD.h" #include "AmpGen/EventType.h" #include "AmpGen/Integrator.h" -#include "AmpGen/Integrator2.h" +#include "AmpGen/IntegratorSIMD.h" #include "AmpGen/Types.h" #include "AmpGen/Event.h" #include "AmpGen/Projection.h" #include "AmpGen/MinuitParameter.h" -//#include "AmpGen/functional/pdf.h" + namespace AmpGen { @@ -40,9 +41,20 @@ namespace AmpGen where @f$\mathcal{P}(\psi)@f$ is the probability, @f$g_i@f$ is the coupling to an isobar channel, and @f$\mathcal{A}_i(\psi)@f$ is the amplitude of the ith channel. */ - class CoherentSum // : public functional::pdf_base + class CoherentSum { public: + #if ENABLE_AVX2 + using EventList_type = EventListSIMD; + using Integrator_type= IntegratorSIMD; + using complex_v = AVX2::complex_t; + using float_v = AVX2::float_t; + #else + using EventList_type = EventList; + using Integrator_type = Integrator; + using complex_v = complex_t; + using float_v = real_t; + #endif CoherentSum(); CoherentSum( const EventType& type, const AmpGen::MinuitParameterSet& mps, const std::string& prefix = "" ); virtual ~CoherentSum() = default; @@ -50,8 +62,8 @@ namespace AmpGen AmplitudeRules protoAmplitudes() { return m_rules; } std::string prefix() const { return m_prefix; } - TransitionMatrix operator[]( const size_t& index ) { return m_matrixElements[index]; } - const TransitionMatrix operator[]( const size_t& index ) const { return m_matrixElements[index]; } + auto operator[]( const size_t& index ) { return m_matrixElements[index]; } + const auto operator[]( const size_t& index ) const { return m_matrixElements[index]; } size_t size() const { return m_matrixElements.size(); } real_t getWeight() const { return m_weight; } @@ -64,10 +76,8 @@ namespace AmpGen complex_t norm( const size_t& x, const size_t& y ) const; complex_t getVal( const Event& evt ) const; - complex_t getVal( const Event& evt, const std::vector& cacheAddresses ) const; complex_t getValNoCache( const Event& evt ) const; - complex_t getValNoCache( const Event& evt, const size_t& offset ) const; - + void transferParameters(); void prepare(); void printVal( const Event& evt ); @@ -75,28 +85,35 @@ namespace AmpGen void setWeight( MinuitProxy param ) { m_weight = param; } void makeTotalExpression(); void reset( bool resetEvents = false ); - void setEvents( EventList& list ); - void setMC( EventList& sim ); + void setEvents( EventList_type& list ); + #if ENABLE_AVX2 + void setEvents( EventList& list) { setEvents( *(new EventListSIMD(list)) ) ; } + void setMC( EventList& list) { setMC( *(new EventListSIMD(list)) ) ; } + float_v operator()( const float_v*, const unsigned) const; + #endif + void setMC( EventList_type& sim ); + void debug( const Event& evt, const std::string& nameMustContain=""); void generateSourceCode( const std::string& fname, const double& normalisation = 1, bool add_mt = false ); - std::vector cacheAddresses( const EventList& evts ) const; std::vector fitFractions( const LinearErrorPropagator& linProp ); - std::vector> matrixElements() const { return m_matrixElements; } + auto matrixElements() const { return m_matrixElements; } std::map> getGroupedAmplitudes(); Bilinears norms() const { return m_normalisations ; } - std::function evaluator(const EventList* = nullptr) const; - KeyedView componentEvaluator(const EventList* = nullptr) const; + std::function evaluator(const EventList_type* = nullptr) const; + KeyedView componentEvaluator(const EventList_type* = nullptr) const; protected: - std::vector> m_matrixElements; ///< Vector of (expanded) matrix elements + std::vector> m_matrixElements; ///< Vector of (expanded) matrix elements Bilinears m_normalisations; ///< Normalisation integrals AmplitudeRules m_rules; ///< Ruleset for the selected transition. - Integrator2 m_integrator; ///< Integral dispatch tool (with default unroll = 10) + + Integrator_type m_integrator; ///< Integral dispatch tool (with default unroll = 10) TransitionMatrix m_total; ///< Total Matrix Element - EventList* m_events = {nullptr}; ///< Data events to evaluate PDF on + EventList_type* m_events = {nullptr}; ///< Data events to evaluate PDF on + EventType m_evtType; ///< Final state for this amplitude size_t m_prepareCalls = {0}; ///< Number of times prepare has been called size_t m_lastPrint = {0}; ///< Last time verbose PDF info was printed diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index d3289d6c4a6..558f3588b56 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -27,216 +27,219 @@ namespace AmpGen WARNING("Asking for the size_of the return buffer of an RTO expression"); return 0; } }; } + template class CompiledExpression; template - class CompiledExpression : public CompiledExpressionBase - { - - private: - DynamicFCN m_fcn; - DynamicFCN>(ARGS...)> m_fdb; - std::vector m_externals = {}; - bool m_hasExternalsChanged = {false}; - - public: - typedef RETURN_TYPE return_type; - - CompiledExpression( const Expression& expression, - const std::string& name, - const std::map& evtMapping = - std::map(), - const DebugSymbols& db = {}, - const MinuitParameterSet* mps = nullptr ) - : CompiledExpressionBase( expression, name, db, evtMapping ) + class CompiledExpression : public CompiledExpressionBase { - resolve(mps); - } - - CompiledExpression( const std::string& name = "" ) : CompiledExpressionBase( name ) {}; - std::vector externBuffer() const { return m_externals ; } - std::string returnTypename() const override { return typeof(); } - std::string fcnSignature() const override - { - return CompiledExpressionBase::fcnSignature(typelist(), use_rto()); - } - bool use_rto() const override { - return std::is_same::value; - } - std::string args() const override - { - std::string signature; - auto argTypes = typelist(); - for( unsigned int i = 0 ; i < argTypes.size(); ++i ) - { - signature += " x"+std::to_string(i) ; - if( i != argTypes.size() - 1 ) signature += ", "; - } - return signature; - } - - void resolve( const MinuitParameterSet* mps=nullptr ) - { - CompiledExpressionBase::resolve(mps); - } - void setExternals( const std::vector& external ) { m_externals = external; } - - unsigned int getNParams() const { return m_externals.size(); } - - void print() const override - { - INFO( "Name = " << name() ); - INFO( "Hash = " << hash() ); - INFO( "IsReady? = " << isReady() << " IsLinked? " << (m_fcn.isLinked() ) ); - INFO( "args = ["<< vectorToString( m_externals, ", ") <<"]"); - for( auto& c : m_cacheTransfers ){ c->print() ; } - } - - void setExternal( const double& value, const unsigned int& address ) override - { - DEBUG( "Setting external " << address << " / " << m_externals.size() << " to value = " << value << " ; current = " << m_externals[address] ); - if ( m_externals[address] == value ) return; - m_externals[address] = value; - m_hasExternalsChanged = true; - } - void resizeExternalCache(const size_t& N ) override { - if( m_externals.size() < N ){ - m_externals.resize(N); - } - } - bool hasExternalsChanged() { return m_hasExternalsChanged; } - void resetExternals() { m_hasExternalsChanged = false; } - Expression& expression() { return m_obj; } - void compileDetails( std::ostream& stream ) const - { - stream << "extern \"C\" int " << progName() << "_pSize () {\n" - << " return " << m_externals.size() << ";\n"; - stream << "}\n"; - - stream << "extern \"C\" double " << progName() << "_pVal (int n) {\n"; - for ( size_t i = 0; i < m_externals.size(); i++ ) - stream << " if(n == " << i << ") return " << m_externals.at( i ) << ";\n"; - stream << " return 0;\n}\n"; - } + private: + DynamicFCN m_fcn; + DynamicFCN m_batchFcn; + DynamicFCN>(ARGS...)> m_fdb; + std::vector m_externals = {}; + bool m_hasExternalsChanged = {false}; + + public: + typedef RETURN_TYPE return_type; + + CompiledExpression( const Expression& expression, + const std::string& name, + const std::map& evtMapping = + std::map(), + const DebugSymbols& db = {}, + const MinuitParameterSet* mps = nullptr ) + : CompiledExpressionBase( expression, name, db, evtMapping ) + { + resolve(mps); + } + + CompiledExpression( const std::string& name = "" ) : CompiledExpressionBase( name ) {}; + std::vector externBuffer() const { return m_externals ; } + std::string returnTypename() const override { return typeof(); } + std::string fcnSignature() const override + { + return CompiledExpressionBase::fcnSignature(typelist(), use_rto()); + } + bool use_rto() const override { + return std::is_same::value; + } + std::string args(bool includeTypes = false) const override + { + std::string signature; + auto argTypes = typelist(); + for( unsigned int i = 0 ; i < argTypes.size(); ++i ) + { + signature += (includeTypes ? argTypes[i] : "") + " x"+std::to_string(i) ; + if( i != argTypes.size() - 1 ) signature += ", "; + } + return signature; + } + + void resolve( const MinuitParameterSet* mps=nullptr ) + { + CompiledExpressionBase::resolve(mps); + } + void setExternals( const std::vector& external ) { m_externals = external; } + + unsigned int getNParams() const { return m_externals.size(); } + + void print() const override + { + INFO( "Name = " << name() ); + INFO( "Hash = " << hash() ); + INFO( "IsReady? = " << isReady() << " IsLinked? " << (m_fcn.isLinked() ) ); + INFO( "args = ["<< vectorToString( m_externals, ", ") <<"]"); + for( auto& c : m_cacheTransfers ){ c->print() ; } + } + + void setExternal( const double& value, const unsigned int& address ) override + { + DEBUG( "Setting external " << address << " / " << m_externals.size() << " to value = " << value << " ; current = " << m_externals[address] ); + if ( m_externals[address] == value ) return; + m_externals[address] = value; + m_hasExternalsChanged = true; + } + void resizeExternalCache(const size_t& N ) override { + if( m_externals.size() < N ){ + m_externals.resize(N); + } + } + bool hasExternalsChanged() { return m_hasExternalsChanged; } + void resetExternals() { m_hasExternalsChanged = false; } + + Expression& expression() { return m_obj; } + + void compileDetails( std::ostream& stream ) const + { + stream << "extern \"C\" int " << progName() << "_pSize () {\n" + << " return " << m_externals.size() << ";\n"; + stream << "}\n"; + + stream << "extern \"C\" double " << progName() << "_pVal (int n) {\n"; + for ( size_t i = 0; i < m_externals.size(); i++ ) + stream << " if(n == " << i << ") return " << m_externals.at( i ) << ";\n"; + stream << " return 0;\n}\n"; + } + void compileBatch( std::ostream& stream ) const + { + stream << "#include \n"; + stream << "extern \"C\" void " << progName() + << "_batch(" << returnTypename() << "* rt" + << ", const size_t& N, " + << " const size_t& eventSize, " + << " const size_t& cacheSize, " << args(true) << ") {\n"; + stream << "#pragma omp parallel for\n"; + stream << "for( unsigned int i = 0; i != N/8; ++i ){\n"; + stream << " rt[cacheSize*i] = " << progName() + "( x0, x1 + i * eventSize);"; + stream << "}\n}"; + } + + void compileWithParameters( std::ostream& stream ) const + { + DEBUG( "Compiling " << name() << " = " << hash() ); + stream << "extern \"C\" " << returnTypename() << " " << progName() << "_wParams" + << "( const double*__restrict__ E ){" << std::endl; + stream << " double externalParameters [] = {" << (m_externals.size() == 0 ? "0" : vectorToString(m_externals,", ") ) <<"};\n" ; + stream << " return " << progName() << "( externalParameters, E ); // E is P \n}\n"; + } + + bool isReady() const override { return m_fcn.isLinked(); } + bool isLinked() const { return m_fcn.isLinked() ; } + + unsigned returnTypeSize() const override { return detail::size_of()(); } + + template < class T > + RETURN_TYPE operator()( const T* event ) const + { + return m_fcn( m_externals.data(), event ); + } + RETURN_TYPE operator()( const ARGS&... args ) const + { + return m_fcn( args... ); + } + template void batch( arg_types... args ) const { + m_batchFcn(args...); + } + + template < class T> + void debug( const T* event ) const + { + if ( !m_fcn.isLinked() ) { + FATAL( "Function " << name() << " not linked" ); + } + if ( !m_fdb.isLinked() ) { + FATAL( "Function" << name() << " debugging symbols not linked" ); + } + std::vector> debug_results; + if constexpr(std::is_same::value) debug_results = m_fdb( nullptr, &( m_externals[0] ), event ); + else debug_results = m_fdb( &(m_externals[0]), event); + for( auto& debug_result : debug_results ){ + auto val = debug_result.second; + auto label = debug_result.first; + if( std::real(val) == -999. ) std::cout << bold_on << std::setw(50) << std::left << label << bold_off << std::endl; + else if( std::imag(val) == 0 ) std::cout << " " << std::setw(50) << std::left << label << " = " << std::real(val) << std::endl; + else std::cout << " " << std::setw(50) << std::left << label << " = " << val << std::endl; + } + } + + bool link( void* handle ) override + { + const std::string symbol = progName() ; + bool status = true; + status &= m_fcn.set(handle, symbol, true); + status &= m_db.size() == 0 || m_fdb.set(handle, symbol + "_DB"); + status &= !m_enableBatch || m_batchFcn.set(handle, symbol + "_batch"); + return status; + } + bool link( const std::string& handle ) override + { + return link( dlopen( handle.c_str(), RTLD_NOW ) ); + }; + }; - void compileWithParameters( std::ostream& stream ) const + template + CompiledExpression + make_rto_expression( const Expression& expression, const std::string& name , const bool& verbose=false) { - DEBUG( "Compiling " << name() << " = " << hash() ); - stream << "extern \"C\" " << returnTypename() << " " << progName() << "_wParams" - << "( const double*__restrict__ E ){" << std::endl; - stream << " double externalParameters [] = {" << (m_externals.size() == 0 ? "0" : vectorToString(m_externals,", ") ) <<"};\n" ; - stream << " return " << progName() << "( externalParameters, E ); // E is P \n}\n"; + CompiledExpression rt(expression,name); + rt.compile(); + rt.prepare(); + return rt; } - bool isReady() const override { return m_fcn.isLinked(); } - bool isLinked() const { return m_fcn.isLinked() ; } - - unsigned returnTypeSize() const override { return detail::size_of()(); } - - template < class T > - RETURN_TYPE operator()( const T* event ) const - { - return m_fcn( (const double*)( &( m_externals[0] ) ), event ); - } - RETURN_TYPE operator()( const ARGS&... args ) const - { - return m_fcn( args... ); - } - template < class T> - void debug( const T* event ) const + template + CompiledExpression + make_expression( const Expression& expression, const std::string& name , const bool& verbose=false) { - if ( !m_fcn.isLinked() ) { - FATAL( "Function " << name() << " not linked" ); - } - if ( !m_fdb.isLinked() ) { - FATAL( "Function" << name() << " debugging symbols not linked" ); - } - std::vector> debug_results; - if constexpr(std::is_same::value) debug_results = m_fdb( nullptr, &( m_externals[0] ), event ); - else debug_results = m_fdb( &(m_externals[0]), event); - for( auto& debug_result : debug_results ){ - auto val = debug_result.second; - auto label = debug_result.first; - if( std::real(val) == -999. ) std::cout << bold_on << std::setw(50) << std::left << label << bold_off << std::endl; - else if( std::imag(val) == 0 ) std::cout << " " << std::setw(50) << std::left << label << " = " << std::real(val) << std::endl; - else std::cout << " " << std::setw(50) << std::left << label << " = " << val << std::endl; - } + CompiledExpression rt(expression,name); + rt.compile(); + rt.prepare(); + return rt; } - - bool link( void* handle ) override + template + CompiledExpression + make_expression( const Expression& expression, + const std::string& name, + const MinuitParameterSet& mps ) { - const std::string symbol = progName() ; - if ( m_fcn.set( handle, symbol ) == 0 ) { - ERROR( dlerror() ); - FATAL( name() << " (symbol = " << symbol << ") linking fails" ); - return false; - } - if ( m_db.size() ==0 ) return true; - if ( m_fdb.set( handle, progName() + "_DB" ) == 0 ) { - ERROR( "Linking of " << name() << " symbol = " << symbol << ") for debugging fails" ); - return false; - } - return true; + CompiledExpression rt(expression,name,{},{},&mps); + rt.compile(); + rt.prepare(); + return rt; } - bool link( const std::string& handle ) override + template + CompiledExpression + make_expression( const Expression& expression, + const std::string& name, + const std::map & evtMap, + const MinuitParameterSet& mps ) { - DEBUG( "Linking " << name() << ( m_db.size() !=0 ? " (debugging)" : "" ) << " hash = " << hash() ); - const std::string symbol = progName(); - if ( m_fcn.set( handle, symbol ) == 0 ) { - ERROR( "Function not linked: " << name() << " (sym="<< symbol << ")" ); - return false; - } - if ( m_db.size() ==0 ) return true; - const std::string dbsymbol = symbol + "_DB"; - if ( m_fdb.set( handle, dbsymbol ) == 0 ) { - ERROR( "Linking of " << name() << " symbol = " << dbsymbol << ")" ); - return false; - } - return true; + CompiledExpression rt(expression,name,evtMap,{},&mps); + rt.compile(); + rt.prepare(); + return rt; } - }; - template - CompiledExpression - make_rto_expression( const Expression& expression, const std::string& name , const bool& verbose=false) - { - CompiledExpression rt(expression,name); - rt.compile(); - rt.prepare(); - return rt; - } - - template - CompiledExpression - make_expression( const Expression& expression, const std::string& name , const bool& verbose=false) - { - CompiledExpression rt(expression,name); - rt.compile(); - rt.prepare(); - return rt; - } - template - CompiledExpression - make_expression( const Expression& expression, - const std::string& name, - const MinuitParameterSet& mps ) - { - CompiledExpression rt(expression,name,{},{},&mps); - rt.compile(); - rt.prepare(); - return rt; - } - template - CompiledExpression - make_expression( const Expression& expression, - const std::string& name, - const std::map & evtMap, - const MinuitParameterSet& mps ) - { - CompiledExpression rt(expression,name,evtMap,{},&mps); - rt.compile(); - rt.prepare(); - return rt; - } } // namespace AmpGen diff --git a/AmpGen/CompiledExpressionBase.h b/AmpGen/CompiledExpressionBase.h index d1e26ea9a7a..d80f542b090 100644 --- a/AmpGen/CompiledExpressionBase.h +++ b/AmpGen/CompiledExpressionBase.h @@ -41,24 +41,26 @@ namespace AmpGen void resolve(const MinuitParameterSet* mps = nullptr); void prepare(); void compile(const std::string& fname=""); + virtual void compileBatch( std::ostream& stream ) const = 0; void to_stream( std::ostream& stream ) const; unsigned int hash() const; std::string name() const; std::string progName() const; - virtual bool link( void* handle ) = 0; - virtual bool link( const std::string& handle ) = 0; - virtual void setExternal( const double& value, const unsigned int& address ) = 0; - virtual void resizeExternalCache( const size_t& N ) = 0; + virtual bool link( void*) = 0; + virtual bool link( const std::string&) = 0; + virtual void setExternal(const double&, const unsigned&) = 0; + virtual void resizeExternalCache(const size_t&) = 0; virtual bool isReady() const = 0; virtual std::string returnTypename() const = 0; virtual std::string fcnSignature() const = 0; - virtual std::string args() const = 0; + virtual std::string args(bool=false) const = 0; virtual void print() const = 0; virtual ~CompiledExpressionBase(); virtual unsigned returnTypeSize() const = 0; - static std::string fcnSignature(const std::vector& argList, bool rto); + static std::string fcnSignature(const std::vector&, bool); virtual bool use_rto() const = 0; Expression expression() const { return m_obj; } + void enableBatch() { m_enableBatch = true ; } protected: Expression m_obj; std::string m_name; @@ -69,6 +71,8 @@ namespace AmpGen std::vector> m_debugSubexpressions; std::vector> m_cacheTransfers; std::shared_ptr m_resolver; + std::vector m_additionalHeaders; + bool m_enableBatch = {false}; private: void addDebug( std::ostream& stream ) const; void addDependentExpressions( std::ostream& stream, size_t& sizeOfStream ) const; diff --git a/AmpGen/CompilerWrapper.h b/AmpGen/CompilerWrapper.h index 0dcbc738147..1e17d9eb03c 100644 --- a/AmpGen/CompilerWrapper.h +++ b/AmpGen/CompilerWrapper.h @@ -21,6 +21,7 @@ namespace AmpGen void compileSource(const std::string& fname, const std::string& oname ); void setVerbose() { m_verbose = true ; } void preamble(std::ostream& os ) const ; + void addHeader(const std::string& include ) { m_includes.push_back(include); } private: std::vector m_includes = {"array","complex","math.h","vector"}; bool m_verbose; diff --git a/AmpGen/DynamicFCN.h b/AmpGen/DynamicFCN.h index d8758b29c90..59157e5c7b7 100644 --- a/AmpGen/DynamicFCN.h +++ b/AmpGen/DynamicFCN.h @@ -50,11 +50,12 @@ namespace AmpGen } return set(m_handle,name); } - bool set( void* handle, const std::string& name ) + bool set( void* handle, const std::string& name, bool isFatal = false) { m_fcn = (RETURN_TYPE( * )( IN_TYPES... ))dlsym( handle, name.c_str() ); if ( m_fcn == nullptr ) { - ERROR( dlerror() ); + if( !isFatal ) ERROR( "Failed to link: " << name << " error: " << dlerror() ); + else FATAL("Failed to link: " << name << " error: " << dlerror() ); return false; } return true; diff --git a/AmpGen/Event.h b/AmpGen/Event.h index bf168f02cd3..5c2145301e7 100644 --- a/AmpGen/Event.h +++ b/AmpGen/Event.h @@ -13,26 +13,26 @@ namespace AmpGen { /** @class Event @brief Encapsulates the final state particles of a single event - Encapsulates the final state particles of a single event, or candidate in the language of proton-proton collisions. Typically will store (i) the event kinematics, i.e. four-momenta, (ii). a cache of complex numbers that contain intermediate calculations of the amplitude, (iii). the weight of the given event/candidate, (iv). The probability that the event was generated with, in the case of a simulated event */ + Encapsulates the final state particles of a single event, or candidate in the language of proton-proton collisions. Typically will store (i) the event kinematics, i.e. four-momenta, (ii). the weight of the given event/candidate, (iii). The probability that the event was generated with, in the case of a simulated event */ class Event { public: - - Event( const unsigned& N, const unsigned& cacheSize=0 ); - Event( const real_t* data, const unsigned& N, const unsigned& cacheSize=0); + Event () = default; + Event( const unsigned& N ); + Event( const real_t* data, const unsigned& N ); void set( const unsigned& i, const std::vector& p ); void set( const unsigned& i, const real_t* p ); void set( const real_t* evt ); void set( const unsigned& i, const real_t& p ) ; void swap( const unsigned int& i , const unsigned int& j ); - void setCache(const complex_t& value, const unsigned& pos) ; - template void setCache( const std::array& value, const unsigned& pos ) - { - std::memmove( m_cache.data() + pos, value.data(), sizeof(std::array) ); - } - void setCache( const std::vector& value, const unsigned& pos ); - void resizeCache( const unsigned int& new_size ); + // void setCache(const complex_t& value, const unsigned& pos) ; + // template void setCache( const std::array& value, const unsigned& pos ) + // { + // std::memmove( m_cache.data() + pos, value.data(), sizeof(std::array) ); + // } + // void setCache( const std::vector& value, const unsigned& pos ); + // void resizeCache( const unsigned int& new_size ); unsigned size() const { return m_event.size(); } @@ -41,7 +41,7 @@ namespace AmpGen { const real_t* address(const unsigned& ref=0) const { return &(m_event[ref]); } real_t* address(const unsigned& ref=0) { return &(m_event[ref]); } - unsigned cacheSize() const { return m_cache.size(); } + // unsigned cacheSize() const { return m_cache.size(); } real_t weight() const { return m_weight; } real_t genPdf() const { return m_genPdf; } real_t operator[](const unsigned& i) const { return m_event[i]; } @@ -49,27 +49,28 @@ namespace AmpGen { operator const real_t*() const { return &(m_event[0]); } operator real_t*() { return &(m_event[0]); } - const complex_t& getCache(const unsigned& pos) const { return m_cache[pos]; } - const complex_t* getCachePtr(const unsigned& pos=0) const { return &(m_cache[0]) + pos; } - complex_t* getCachePtr(const unsigned& pos=0) { return &(m_cache[0]) + pos; } + // const complex_t& getCache(const unsigned& pos) const { return m_cache[pos]; } + // const complex_t* getCachePtr(const unsigned& pos=0) const { return &(m_cache[0]) + pos; } + // complex_t* getCachePtr(const unsigned& pos=0) { return &(m_cache[0]) + pos; } void setWeight( const real_t& weight ){ m_weight = weight ; } void setGenPdf( const real_t& genPdf ){ m_genPdf = genPdf ; } void extendEvent(const real_t& value) { m_event.push_back( value ); } void print() const; - void printCache() const; - + // void printCache() const; + void setIndex(const unsigned& index){ m_index = index; } + unsigned index() const { return m_index; } real_t s( const unsigned& index) const ; real_t s( const unsigned& index1, const unsigned& index2 ) const ; real_t s( const unsigned& index1, const unsigned& index2, const unsigned& index3 ) const; real_t s( const std::vector& indices ) const ; private: std::vector m_event; - std::vector m_cache; + // std::vector m_cache; real_t m_genPdf = {1}; real_t m_weight = {1}; - + unsigned m_index = {0}; inline real_t get(const unsigned& index ) const { return m_event[index]; }; }; } diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 131af735ea0..260cd3affbd 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -31,10 +31,10 @@ namespace AmpGen { private: std::vector m_data = {}; + std::vector m_cache = {}; EventType m_eventType = {}; std::map m_pdfIndex = {}; std::map m_extensions = {}; - size_t m_lastCachePosition = {0}; public: typedef Event value_type; EventList() = default; @@ -71,7 +71,7 @@ namespace AmpGen const Event& at( const size_t& pos ) const { return m_data[pos]; } size_t size() const { return m_data.size(); } double integral() const; - + void reserve( const size_t& size ) { m_data.reserve( size ); } void push_back( const Event& evt ) { m_data.push_back( evt ); } void setEventType( const EventType& type ) { m_eventType = type; } @@ -86,48 +86,50 @@ namespace AmpGen size_t getCacheIndex( const CompiledExpressionBase& PDF, bool& status ) const; size_t getCacheIndex( const CompiledExpressionBase& PDF ) const; - template - size_t registerExpression(const T& expression, const size_t& size_of=0) + template size_t registerExpression(const T& expression, const size_t& size_of=0) { auto key = FNV1a_hash( expression.name() ); auto pdfIndex = m_pdfIndex.find( key ); - if ( pdfIndex != m_pdfIndex.end() ) { - return pdfIndex->second; - } else { - size_t lcp = m_lastCachePosition; - size_t expression_size = size_of == 0 ? - expression.returnTypeSize() / sizeof(complex_t) : size_of; - if (lcp >= at( 0 ).cacheSize() ) { - WARNING("Cache index " << lcp << " exceeds cache size = " - << at(0).cacheSize() << " resizing to " - << lcp + expression_size ); - resizeCache( lcp + expression_size ); - } - m_pdfIndex[key] = m_lastCachePosition; - m_lastCachePosition += expression_size; - return lcp; + if ( pdfIndex != m_pdfIndex.end() ) return pdfIndex->second; + else { + size_t expression_size = size_of == 0 ? expression.returnTypeSize() / sizeof(complex_t) : size_of; + m_pdfIndex[key] = m_cache.size() / m_data.size(); + m_cache.resize( m_cache.size() + m_data.size() * expression_size ); + return m_pdfIndex[key]; } } - + complex_t cache( const unsigned& evtIndex, const unsigned& cacheElement ) + { + unsigned cacheSize = m_cache.size() / m_data.size(); + return m_cache[cacheSize * evtIndex + cacheElement]; + } + void setCache( const complex_t& v, const unsigned& p ) + { + m_cache[p] = v; + } + void setCache( const std::vector& v, const unsigned& p ) + { + std::memmove(m_cache.data() +p, v.data(), sizeof(complex_t) * v.size() ); + } template void updateCache( const FCN& fcn, const size_t& index ) { + unsigned cacheSize = m_cache.size() / m_data.size(); if constexpr( std::is_same< typename FCN::return_type, void >::value ) { #ifdef _OPENMP #pragma omp parallel for #endif - for ( size_t i = 0; i < size(); ++i ) { - fcn( m_data[i].getCachePtr(index), fcn.externBuffer().data(), m_data[i].address() ); + for ( size_t evt = 0; evt < size(); ++evt ) + { + fcn( m_cache.data() + cacheSize*evt +index , fcn.externBuffer().data(), m_data[evt].address() ); } } else { #ifdef _OPENMP #pragma omp parallel for #endif - for ( size_t i = 0; i < size(); ++i ) { - m_data[i].setCache(fcn(m_data[i].address()), index); - } - } + for ( size_t evt = 0; evt < size(); ++evt ) { setCache( fcn(m_data[evt].address() ), cacheSize*evt + index ) ; } + } } void reserveCache(const size_t& index); void resizeCache(const size_t& newCacheSize ); @@ -183,7 +185,6 @@ namespace AmpGen DECLARE_ARGUMENT(Branches, std::vector); DECLARE_ARGUMENT(EntryList, std::vector); DECLARE_ARGUMENT(GetGenPdf, bool); - DECLARE_ARGUMENT(CacheSize, size_t); DECLARE_ARGUMENT(Filter, std::string); DECLARE_ARGUMENT(WeightBranch, std::string); DECLARE_ARGUMENT(ApplySym, bool); diff --git a/AmpGen/EventListSIMD.h b/AmpGen/EventListSIMD.h new file mode 100644 index 00000000000..bad640db26c --- /dev/null +++ b/AmpGen/EventListSIMD.h @@ -0,0 +1,173 @@ +#ifndef AMPGEN_EVENTLIST2_H +#define AMPGEN_EVENTLIST2_H + +#include "AmpGen/ArgumentPack.h" +#include "AmpGen/EventType.h" +#include "AmpGen/MsgService.h" +#include "AmpGen/Event.h" +#include "AmpGen/Projection.h" +#include "AmpGen/Utilities.h" +#include "AmpGen/MetaUtils.h" +#include "AmpGen/EventList.h" +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef _OPENMP + #include +#endif + +#if ENABLE_AVX2 + + #include "AmpGen/simd/avx2_types.h" + #include "AmpGen/simd/iterator.h" + +namespace AmpGen +{ + using float_v = AVX2::float_t; + using complex_v = AVX2::complex_t; + + class CompiledExpressionBase; + class EventListSIMD + { + private: + std::vector m_data = {}; + std::vector m_weights = {}; + std::vector m_genPDF = {}; + std::vector m_cache = {}; + EventType m_eventType = {}; + std::map m_pdfIndex = {}; + unsigned m_eventSize = {0}; + unsigned m_nEvents = {0}; + unsigned m_nBlocks = {0}; + public: + typedef Event value_type; + EventListSIMD() = default; + EventListSIMD( const EventType& type ); + template < class ... ARGS > EventListSIMD( const std::string& fname, const EventType& evtType, const ARGS&... args ) : EventListSIMD(evtType) + { + loadFromFile( fname, ArgumentPack(args...) ); + } + template < class ... ARGS > EventListSIMD( const std::string& fname, const ARGS&... args ) : EventListSIMD() + { + loadFromFile( fname, ArgumentPack(args...) ); + } + template < class ... ARGS > EventListSIMD( const std::vector& fname, const EventType& evtType, const ARGS&... args ) : EventListSIMD(evtType) + { + for( auto& f : fname ) loadFromFile( f, ArgumentPack(args...) ); + } + template < class ... ARGS > EventListSIMD( TTree* tree, const EventType& evtType, const ARGS&... args ) : EventListSIMD(evtType) + { + loadFromTree( tree, ArgumentPack(args...) ); + } + const float_v* data() const { return m_data.data(); } + const AVX2::complex_t* cache() const { return m_cache.data() ; } + EventListSIMD( const EventList& other ); + void resetCache(); + const AVX2::complex_t cache( const unsigned& evtIndex, const unsigned& cachePos ) + { + return m_cache[ (unsigned)(evtIndex/float_v::size) * cacheSize() + cachePos ]; + } + const Event at(const unsigned& p) const { return EventListSIMD::operator[](p) ; } + const float_v* block(const unsigned& p) { return m_data.data() + p * m_eventSize ; } + float_v weight(const unsigned& p) const { return m_weights[p]; } + float_v genPDF(const unsigned& p) const { return m_genPDF[p]; } + const Event operator[]( const size_t&) const; + std::array scatter(unsigned) const; + void gather(const std::array&, unsigned); + auto begin() const { return make_scatter_iterator(0,this); } + auto end() const { return make_scatter_iterator(m_nEvents, (const EventListSIMD*)(nullptr) ); } + auto begin() { return make_scatter_iterator(0, this); } + auto end() { return make_scatter_iterator(m_nEvents, (EventListSIMD*)(nullptr) ); } + EventType eventType() const { return m_eventType; } + size_t aligned_size() const { return nBlocks() * float_v::size; } ///aligned number of events + size_t cacheSize() const { return m_cache.size() / m_nBlocks; } /// number of cached elements + double integral() const; + size_t eventSize() const { return m_eventSize; } + size_t size() const { return m_nEvents ; } + size_t nBlocks() const { return m_nBlocks; } + void reserve( const size_t& size ) { m_data.reserve( size * m_eventType.size() ); } + void setEventType( const EventType& type ) { m_eventType = type; m_eventSize = m_eventType.size(); } + void add( const EventListSIMD& evts ); + void loadFromTree( TTree* tree, const ArgumentPack& args ); + void loadFromFile( const std::string& fname, const ArgumentPack& args ); + void printCacheInfo( const unsigned int& nEvt = 0 ); + void clear(); + + TTree* tree( const std::string& name, const std::vector& extraBranches = {} ) const; + + size_t getCacheIndex( const CompiledExpressionBase& PDF, bool& status ) const; + size_t getCacheIndex( const CompiledExpressionBase& PDF ) const; + template unsigned registerExpression(const T& expression, const unsigned& size_of=0) + { + auto key = FNV1a_hash( expression.name() ); + auto pdfIndex = m_pdfIndex.find( key ); + if ( pdfIndex != m_pdfIndex.end() ) return pdfIndex->second; + else { + unsigned nEvents = aligned_size(); + unsigned expression_size = size_of == 0 ? expression.returnTypeSize() / sizeof(AmpGen::AVX2::complex_t) : size_of; + m_pdfIndex[key] = m_cache.size() / nBlocks(); + m_cache.resize(m_cache.size() + nBlocks() * expression_size); + return m_pdfIndex[key]; + } + } + template void updateCache( const FCN& fcn, const size_t& index ) + { + fcn.batch(m_cache.data() + index, aligned_size(), m_eventSize, cacheSize(), fcn.externBuffer().data(), m_data.data()); + } + void reserveCache(const unsigned& index); + void resizeCache( const unsigned& index); + TH1D* makeProjection(const Projection& projection , const ArgumentPack& args = ArgumentPack()) const; + TH2D* makeProjection(const Projection2D& projection, const ArgumentPack& args = ArgumentPack()) const; + std::vector makeProjections( const std::vector& projections, const ArgumentPack& args ); + + template std::vector makeDefaultProjections( const ARGS&... args ) + { + auto argPack = ArgumentPack( args... ); + size_t nBins = argPack.getArg(100); + auto proj = eventType().defaultProjections(nBins); + return makeProjections( proj , argPack ); + } + + template std::vector makeProjections( const std::vector& projections, const ARGS&... args ) + { + return makeProjections( projections, ArgumentPack( args... ) ); + } + + template , ArgumentPack>::value > > + TH1D* makeProjection( const Projection& projection, const ARGS&... args ) const + { + return makeProjection( projection, ArgumentPack(args...) ); + } + + template , ArgumentPack>::value > > + TH2D* makeProjection( const Projection2D& projection, const ARGS&... args ) + { + return makeProjection( projection, ArgumentPack(args...) ); + } + + template EventListSIMD& transform( functor&& fcn ) + { + for ( auto& event : *this ) fcn( event ); + return *this; + } + static std::vector makeEvent( const Event& event ) + { + std::vector rt( event.size() ); + for( unsigned i = 0 ; i != event.size(); ++i ) rt[i] = event[i]; + return rt; + } + }; + +} // namespace AmpGen +#endif + +#endif diff --git a/AmpGen/Expression.h b/AmpGen/Expression.h index 9c44737404b..85c3f90dca3 100644 --- a/AmpGen/Expression.h +++ b/AmpGen/Expression.h @@ -57,6 +57,11 @@ complex_t X::operator()() const { return F( m_expression() ); } \ std::string X::to_string(const ASTResolver* resolver) const { return std::string(#F)+"("+ m_expression.to_string(resolver)+")";} +#define DEFINE_UNARY_OPERATOR_NO_RESOLVER( X, F ) \ + X::X( const AmpGen::Expression& expression) : IUnaryExpression(expression) {} \ + X::operator Expression() const { return Expression( std::make_shared(*this) ) ; } \ + complex_t X::operator()() const { return F( m_expression() ); } + /// @ingroup ExpressionEngine macro DECLARE_UNARY_OPERATOR /// Macro to declare a unary operator, \ref ExpressionEngine "see IUnaryExpression" #define DECLARE_UNARY_OPERATOR( X ) \ diff --git a/AmpGen/Generator.h b/AmpGen/Generator.h index 761e954e4bb..e55372e71b4 100644 --- a/AmpGen/Generator.h +++ b/AmpGen/Generator.h @@ -33,20 +33,29 @@ namespace AmpGen m_rnd = rand; m_gps.setRandom( m_rnd ); } - void fillEventListPhaseSpace( EventList& list, const size_t& N, const size_t& cacheSize = 0 ) + void fillEventListPhaseSpace( EventList& list, const size_t& N) { - fillEventListPhaseSpace( list, N, cacheSize, []( const Event& evt ) { return 1; } ); + list.reserve( N ); + while( list.size() < N ){ + Event newEvent = m_gps.makeEvent(); + newEvent.setWeight( 1 ); + newEvent.setIndex( list.size() ); + list.push_back( newEvent ); + } } void setBlockSize( const size_t& blockSize ) { m_generatorBlock = blockSize; } void setNormFlag( const bool& normSetting ) { m_normalise = normSetting; } - template void fillEventListPhaseSpace( EventList& list, const size_t& N, const size_t& cacheSize, HARD_CUT cut ) + template void fillEventListPhaseSpace( EventList& list, const size_t& N, HARD_CUT cut) { list.reserve( N ); while( list.size() < N ){ - Event newEvent = m_gps.makeEvent( cacheSize ); + Event newEvent = m_gps.makeEvent(); newEvent.setWeight( 1 ); - if ( cut( newEvent ) ) list.push_back( newEvent ); + if ( cut( newEvent ) ){ + newEvent.setIndex( list.size() ); + list.push_back( newEvent ); + } } } @@ -74,7 +83,7 @@ namespace AmpGen while ( list.size() - size0 < N ) { EventList mc( m_eventType ); t_phsp.start(); - fillEventListPhaseSpace( mc, m_generatorBlock, pdf.size(), cut ); + fillEventListPhaseSpace(mc, m_generatorBlock, cut); t_phsp.stop(); t_eval.start(); pdf.setEvents( mc ); @@ -136,10 +145,10 @@ namespace AmpGen fillEventList( pdf, evts, nEvents ); return evts; } - EventList generate(const size_t& nEvents, const size_t& cacheSize=0) + EventList generate(const size_t& nEvents) { EventList evts( m_eventType ); - fillEventListPhaseSpace( evts, nEvents, cacheSize ); + fillEventListPhaseSpace( evts, nEvents); return evts; } }; diff --git a/AmpGen/Integrator.h b/AmpGen/Integrator.h index 5312012b13b..a83cce80da2 100644 --- a/AmpGen/Integrator.h +++ b/AmpGen/Integrator.h @@ -51,231 +51,80 @@ namespace AmpGen Integral(const size_t& i, const size_t& j, TransferFCN t) : i(i), j(j), transfer(t) {} }; -/* - template - class Integrator - { - private: - typedef const complex_t& arg; - size_t m_counter = {0}; - std::array, NROLL> m_integrals; - EventList* m_events = {nullptr}; - void calculate() - { - integrateBlock(); - m_counter = 0; - } - void integrateBlock() - { - real_t re[NROLL] = {0}; - real_t im[NROLL] = {0}; - #pragma omp parallel for reduction(+: re, im) - for ( size_t i = 0; i < m_events->size(); ++i ) { - auto& evt = ( *m_events )[i]; - real_t w = evt.weight() / evt.genPdf(); - for ( size_t roll = 0; roll < NROLL; ++roll ) { - auto c = evt.getCache(m_integrals[roll].i) * std::conj(evt.getCache(m_integrals[roll].j)); - re[roll] += w * std::real(c); - im[roll] += w * std::imag(c); - } - } - real_t nv = m_events->norm(); - for ( size_t j = 0; j < m_counter; ++j ) - m_integrals[j].transfer( complex_t( re[j], im[j] ) / nv ); - } + class Integrator + { + typedef const complex_t& arg; + typedef std::function TransferFCN; - public: - Integrator( EventList* events = nullptr ) : m_events( events ){} - - double norm() { return m_events->norm(); } - bool isReady() const { return m_events != nullptr; } - EventList& events() { return *m_events; } - const EventList& events() const { return *m_events; } - void reserveCache(const unsigned& size){ m_events->reserveCache(size); } - template - void addIntegral( const T1& f1, const T2& f2, const Integral::TransferFCN& tf ) - { - addIntegralKeyed( m_events->getCacheIndex(f1), m_events->getCacheIndex(f2), tf ); - } - void queueIntegral(const size_t& i, const size_t& j, complex_t* result){ - addIntegralKeyed(i, j, [result](arg& val){ *result = val ; } ); - } - void queueIntegral(const size_t& c1, - const size_t& c2, - const size_t& i, - const size_t& j, - Bilinears* out, - const bool& sim = true ) - { - if( ! out->workToDo(i,j) )return; - if( sim ) - addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ - out->set(i,j,val); - if( i != j ) out->set(j,i, std::conj(val) ); } ); - else - addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ out->set(i,j,val); } ); - } - void addIntegralKeyed(const size_t& c1, const size_t& c2, const Integral::TransferFCN& tf ) - { - m_integrals[m_counter++] = Integral(c1, c2, tf); - if ( m_counter == NROLL ) calculate(); - } + public: + explicit Integrator( const EventList* events = nullptr ); - void flush() - { - if ( m_counter == 0 ) return; - calculate(); - } - template - void prepareExpression( const EXPRESSION& expression, const size_t& size_of = 0 ) - { - if( m_events == nullptr ) return; - auto index = m_events->registerExpression( expression , size_of ); - m_events->updateCache( expression, index ); - } - size_t getCacheIndex(const CompiledExpressionBase& expression) const { - return m_events->getCacheIndex(expression); + bool isReady() const; + const EventList* events() const; + void queueIntegral(const size_t& c1, + const size_t& c2, + const size_t& i, + const size_t& j, + Bilinears* out, + const bool& sim = true); + void addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ); + void queueIntegral(const size_t& i, const size_t& j, complex_t* result); + void flush(); + void setBuffer( complex_t* pos, const complex_t& value, const size_t& size ); + void setBuffer( complex_t* pos, const std::vector& value, const size_t& size); + complex_t get(const unsigned& i, const unsigned& evt) const { return m_cache[i * m_events->size() + evt ]; } + template unsigned getCacheIndex( const T& t ) const { return m_index.find( t.name() )->second.first; } + double norm() const { return m_norm; } + template void allocate( const std::vector& expressions, const size_t& size_of = 0) + { + if( m_events == nullptr ) return; + unsigned totalSize = 0; + for( unsigned i = 0; i != expressions.size(); ++i ){ + size_t vsize = size_of == 0 ? expressions[i].returnTypeSize() / sizeof(complex_t) : size_of; + m_index[ expressions[i].name() ] = std::make_pair(totalSize, vsize); + totalSize += vsize; } - }; - */ - template - class BinnedIntegrator - { - private: - typedef const std::vector>& arg; - typedef std::function TransferFCN; - - size_t m_counter = {0}; - std::vector m_view = {0}; - std::vector m_slice = {0}; - std::array, NROLL> m_integrals; - EventList* m_events = {nullptr}; - real_t m_norm = {0}; - void calculate() - { - integrateBlock(); - m_counter = 0; - } - void integrateBlock() + m_cache.resize( m_events->size() * totalSize ); + } + + template void prepareExpression(const T& expression) + { + if( m_events == nullptr ) return; + auto f = m_index.find( expression.name() ); + if( f == m_index.end() ) FATAL("Expression: " << expression.name() << " is not registed"); + auto [p0, s] = f->second; + INFO("Preparing: " << expression.name() << " index = " << p0 << " with: " << s << " values" ); + if constexpr( std::is_same< typename T::return_type, void >::value ) { - double re[( NBINS + 1 ) * NROLL] = {0}; - double im[( NBINS + 1 ) * NROLL] = {0}; - auto ij = [&]( const Event& evt, const unsigned int& i, const unsigned int& j ) { - return evt.getCache( i ) * std::conj( evt.getCache( j ) ); - }; - if ( m_slice.size() == 0 ) { - #pragma omp parallel for reduction( + : re, im ) - for ( unsigned int i = 0; i < m_events->size(); ++i ) { - auto& evt = ( *m_events )[i]; - size_t binNo = m_view[i]; - double w = evt.weight() / evt.genPdf(); - for ( unsigned int roll = 0; roll < NROLL; ++roll ) { - auto c = ij( evt, m_integrals[roll].i, m_integrals[roll].j ); - DEBUG( "pos = " << roll * NBINS + binNo << " val = " << w * c ); - re[roll * NBINS + binNo] += w * std::real( c ); - im[roll * NBINS + binNo] += w * std::imag( c ); - } - } - } else { - #pragma omp parallel for reduction( + : re, im ) - for ( unsigned int i = 0; i < m_slice.size(); ++i ) { - auto& evt = ( *m_events )[m_slice[i]]; - size_t binNo = m_view[i]; - double w = evt.weight() / evt.genPdf(); - for ( unsigned int roll = 0; roll < NROLL; ++roll ) { - auto c = ij( evt, m_integrals[roll].i, m_integrals[roll].j ); - re[roll * NBINS + binNo] += w * std::real( c ); - im[roll * NBINS + binNo] += w * std::imag( c ); - } - } - } - for ( size_t thisIntegral = 0; thisIntegral < m_counter; ++thisIntegral ) { - std::vector> tmpBins( NBINS ); - size_t offset = thisIntegral * NBINS; - for ( size_t nBin = 0; nBin < NBINS; ++nBin ) - tmpBins[nBin] = std::complex( re[offset + nBin], im[offset + nBin] ) / m_norm; - m_integrals[thisIntegral].transfer( tmpBins ); + #ifdef _OPENMP + #pragma omp parallel for + #endif + for ( size_t i = 0; i < m_events->size(); ++i ) + { + std::vector buf(s); + expression(&buf[0], expression.externBuffer().data(), m_events->at(i).address() ); + for( unsigned j = 0; j != s; ++j ) m_cache[ (p0+j) * m_events->size() + i] = buf[j]; } } - public: - BinnedIntegrator( EventList* events = nullptr ) : m_events( events ) - { - if( m_events == nullptr ) return; - for ( const auto& event : *m_events ) m_norm += event.weight() / event.genPdf(); - } - void setView( const std::function& binNumber ) - { - if ( m_slice.size() == 0 ) { - if ( m_view.size() != m_events->size() ) m_view.resize( m_events->size() ); - for ( unsigned int i = 0; i < m_events->size(); ++i ) { - - m_view[i] = binNumber( ( *m_events )[i] ); - - if ( m_view[i] >= NBINS ) { - m_view[i] = NBINS; - WARNING( "Event " << m_slice[i] << " bin number = " << m_view[i] << " is out of range!" ); - } - } - } else { - if ( m_view.size() != m_slice.size() ) m_view.resize( m_slice.size() ); - for ( unsigned int i = 0; i < m_slice.size(); ++i ) { - m_view[i] = binNumber( ( *m_events )[m_slice[i]] ); - if ( m_view[i] >= NBINS ) { - m_view[i] = NBINS; - WARNING( "Event " << m_slice[i] << " bin number = " << m_view[i] << " is out of range!" ); - } - } - } + else { + #ifdef _OPENMP + #pragma omp parallel for + #endif + for ( size_t i = 0; i < m_events->size(); ++i ) + setBuffer( &(m_cache[p0 * m_events->size() +i] ), expression(m_events->at(i).address()),s ); } - void setSlice( const std::function& sliceFunction ) - { - if ( m_slice.size() != 0 ) m_slice.clear(); - for ( unsigned int i = 0; i < m_events->size(); ++i ) - if ( sliceFunction( ( *m_events )[i] ) ) m_slice.push_back( i ); - } - - template - void addIntegral( const T1& f1, const T2& f2, const TransferFCN& tFunc ) - { - m_integrals[m_counter++] = Integral( m_events->getCacheIndex( f1 ), m_events->getCacheIndex( f2 ), tFunc ); - if ( m_counter == NROLL ) calculate(); - } - void flush() - { - if ( m_counter == 0 ) return; - calculate(); - } - template - void update( FCN& fcn, std::array& normalisations ) - { - auto mE = fcn.matrixElements(); - auto size = mE.size(); - std::vector toUpdate; - std::vector integralHasChanged( size * size ); - for ( size_t x = 0; x < size; ++x ) { - auto& pdf = mE[x].amp; - pdf.prepare(); - if ( !pdf.hasExternalsChanged() ) continue; - m_events->updateCache( pdf, m_events->getCacheIndex( pdf ) ); - toUpdate.push_back( x ); - } - for ( auto& i : toUpdate ) { - DEBUG( "Updating: " << mE[i].decayTree->uniqueString() ); - for ( unsigned int j = 0; j < size; ++j ) { - if ( integralHasChanged[i * size + j] ) continue; - integralHasChanged[i * size + j] = true; - integralHasChanged[j * size + i] = true; - - addIntegral( mE[i].amp, mE[j].amp, - [i, j, &normalisations]( const auto& val ) { - for ( unsigned int bin = 0; bin < NBINS; ++bin ) { - normalisations[bin].set( i, j, val[bin] ); - if ( i != j ) normalisations[bin].set( j, i, std::conj( val[bin] ) ); - } - } ); - } - } - } - }; + } + + private: + static constexpr size_t N = {10}; ///unroll factor + size_t m_counter = {0}; /// + std::array, N> m_integrals; + const EventList* m_events = {nullptr}; + std::vector m_cache; + std::vector m_weight; + std::map> m_index; + double m_norm = {0}; + void integrateBlock(); + }; } // namespace AmpGen #endif diff --git a/AmpGen/Integrator2.h b/AmpGen/Integrator2.h deleted file mode 100644 index f13efd1ad6f..00000000000 --- a/AmpGen/Integrator2.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef AMPGEN_INTEGRATOR2_H -#define AMPGEN_INTEGRATOR2_H 1 - -#include "AmpGen/Integrator.h" - -namespace AmpGen { - /// test /// - class Integrator2 - { - typedef const complex_t& arg; - typedef std::function TransferFCN; - - public: - explicit Integrator2( const EventList* events = nullptr ); - - bool isReady() const; - const EventList& events() const; - void queueIntegral(const size_t& c1, - const size_t& c2, - const size_t& i, - const size_t& j, - Bilinears* out, - const bool& sim = true); - void addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ); - void queueIntegral(const size_t& i, const size_t& j, complex_t* result); - void flush(); - void setBuffer( complex_t* pos, const complex_t& value, const size_t& size ); - void setBuffer( complex_t* pos, const std::vector& value, const size_t& size); - void reserveCache(const unsigned int& size){}; - complex_t get(const unsigned& i, const unsigned& evt) const { return m_buffer[i][evt]; } - double norm() const { return m_norm; } - template size_t getCacheIndex(const T& expression) const - { - return m_index.find(expression.name())->second; - } - template void prepareExpression( const T& expression, const size_t& size_of = 0 ) - { - if( m_events == nullptr ) return; - size_t vsize = size_of == 0 ? expression.returnTypeSize() / sizeof(complex_t) : size_of; - auto it = m_index.find( expression.name() ); - auto index = 0; - if( it == m_index.end() ) - { - index = m_buffer.size(); - m_index[ expression.name() ] = index; - m_buffer.resize(index+vsize); - for(size_t j = 0 ; j != vsize; ++j ) m_buffer[index+j].resize( m_events->size() ); - } - else index = it->second; - if constexpr( std::is_same< typename T::return_type, void >::value ) - { - #ifdef _OPENMP - #pragma omp parallel for - #endif - for ( size_t i = 0; i < m_events->size(); ++i ) - { - std::vector buf(vsize); - expression(&buf[0], expression.externBuffer().data(), m_events->at(i).address() ); - for( unsigned j = 0; j != vsize; ++j ) m_buffer[index+j][i] = buf[j]; - //expression(&(m_buffer[index][i]), expression.externBuffer().data(), m_events->at(i).address() ); - } - } - else { - #ifdef _OPENMP - #pragma omp parallel for - #endif - for ( size_t i = 0; i < m_events->size(); ++i ) - setBuffer( &(m_buffer[index][i]), expression(m_events->at(i).address()), vsize ); - } - } - - private: - static constexpr size_t N = {10}; ///unroll factor - size_t m_counter = {0}; /// - std::array, N> m_integrals; - const EventList* m_events = {nullptr}; - std::vector> m_buffer; - std::vector m_weight; - std::map m_index; - double m_norm = {0}; - void integrateBlock(); - }; -} -#endif diff --git a/AmpGen/IntegratorSIMD.h b/AmpGen/IntegratorSIMD.h new file mode 100644 index 00000000000..2e166cd1294 --- /dev/null +++ b/AmpGen/IntegratorSIMD.h @@ -0,0 +1,73 @@ +#ifndef AMPGEN_INTEGRATORSIMD_H +#define AMPGEN_INTEGRATORSIMD_H 1 + +#if ENABLE_AVX2 + +#include "AmpGen/Integrator.h" +#include "AmpGen/simd/avx2_types.h" +#include "AmpGen/EventListSIMD.h" + +namespace AmpGen { + /// test /// + class IntegratorSIMD + { + typedef const complex_t& arg; + typedef std::function TransferFCN; + + public: + explicit IntegratorSIMD( const EventListSIMD* events = nullptr ); + + bool isReady() const; + void queueIntegral(const size_t& c1, + const size_t& c2, + const size_t& i, + const size_t& j, + Bilinears* out, + const bool& sim = true); + void addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ); + void queueIntegral(const size_t& i, const size_t& j, complex_t* result); + void flush(); + complex_t get(const unsigned& i, const unsigned& evt) const { return m_cache[i * m_events->size() + evt/float_v::size ].at( evt % float_v::size ); } + template unsigned getCacheIndex( const T& t ) const { return m_index.find( t.name() )->second.first; } + double norm() const { return m_norm; } + const EventListSIMD* events() const { return m_events; } + template void allocate( const std::vector& expressions, const size_t& size_of = 0) + { + if( m_events == nullptr ) return; + unsigned totalSize = 0; + for( unsigned i = 0; i != expressions.size(); ++i ){ + size_t vsize = size_of == 0 ? expressions[i].returnTypeSize() / sizeof(AVX2::complex_t) : size_of; + m_index[ expressions[i].name() ] = std::make_pair(totalSize, vsize); + totalSize += vsize; + } + m_cache.resize( m_events->size() * totalSize ); + } + + template void prepareExpression(const T& expression) + { + if( m_events == nullptr ) return; + auto f = m_index.find( expression.name() ); + if( f == m_index.end() ) FATAL("Expression: " << expression.name() << " is not registed"); + auto [p0, s] = f->second; + expression.batch(m_cache.data() + p0*m_events->aligned_size(), + m_events->aligned_size(), + m_events->eventSize(), + 1, + expression.externBuffer().data(), + m_events->data() ); + } + + private: + static constexpr size_t N = {10}; ///unroll factor + size_t m_counter = {0}; /// + std::array, N> m_integrals; + const EventListSIMD* m_events = {nullptr}; + std::vector m_cache; + std::vector m_weight; + std::map> m_index; + double m_norm = {0}; + void integrateBlock(); + }; +} +#endif +#endif diff --git a/AmpGen/LiteSpan.h b/AmpGen/LiteSpan.h index ac1a4548d60..ed4692a015b 100644 --- a/AmpGen/LiteSpan.h +++ b/AmpGen/LiteSpan.h @@ -27,14 +27,12 @@ namespace AmpGen { typedef typename container_type::value_type value_type; public: KeyedView( const container_type& container, const unsigned width ) : - m_begin( &(container[0]) ), + m_container(&container), m_cache( width * container.size(),0 ), m_width(width), m_size(container.size()), m_keys( width, "") {} - unsigned index(const value_type& it) const { - if( &it - m_begin < 0 || &it -m_begin >= m_size ) ERROR("Invalid address: " << &it - m_begin ); - return &it -m_begin; } + unsigned index(const value_type& it) const { return it.index() ; } const std::string& key(const unsigned int& column ) const { return m_keys[column] ; } const return_type* operator()( const value_type& it ) const { if( m_width *index(it) >= m_cache.size()) ERROR("Out-of-bounds access : " << index(it) ); @@ -48,7 +46,7 @@ namespace AmpGen { unsigned int column, const std::string& key = "") { - for( unsigned i = 0 ; i != m_size; ++i ) m_cache[ i*m_width + column] = functor(m_begin[i]); + for(const auto& element : *m_container) m_cache[ element.index() * m_width + column] = functor(element); if( key != "" ) m_keys[column] = key; } cache_type& operator()(const value_type& it, const unsigned entry ) { @@ -58,11 +56,11 @@ namespace AmpGen { void setKey(const unsigned& column, const std::string& key ) { m_keys[column] = key ; } void print() { - INFO( "width = " << m_width << ", size = " << m_size << " begin = " << m_begin << " keys = " << vectorToString( m_keys , " ") << " cache size = " << m_cache.size() ); + INFO( "width = " << m_width << ", size = " << m_size << " keys = " << vectorToString( m_keys , " ") << " cache size = " << m_cache.size() ); for( unsigned int i = 0 ; i != m_width ; ++i ) std::cout << m_cache[i] << " "; } private: - const value_type* m_begin; + const container_type* m_container; std::vector m_cache; unsigned m_width; unsigned m_size; diff --git a/AmpGen/PhaseSpace.h b/AmpGen/PhaseSpace.h index 9f462bedc66..2d3f37257d6 100644 --- a/AmpGen/PhaseSpace.h +++ b/AmpGen/PhaseSpace.h @@ -29,7 +29,7 @@ namespace AmpGen bool setDecay( const double& m0, const std::vector& mass ); ///< Set the parameters of this phase space generator void setRandom( TRandom* rand ) { m_rand = rand; } ///< Set the random number used by this phase space generator size_t size() const { return m_nt; } ///< Return the number of decay products - Event makeEvent( const size_t& cacheSize = 0 ); ///< Make an event in this phase space. + Event makeEvent(); ///< Make an event in this phase space. EventType eventType() const; ///< Returns the EventType that this phase space is generating void provideEfficiencyReport(const std::vector& report){} diff --git a/AmpGen/Plots.h b/AmpGen/Plots.h deleted file mode 100644 index 7f8c81388fa..00000000000 --- a/AmpGen/Plots.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef AMPGEN_PLOTS_H -#define AMPGEN_PLOTS_H -#include "AmpGen/ErrorPropagator.h" -#include "AmpGen/EventList.h" -#include "AmpGen/CoherentSum.h" -#include "AmpGen/IncoherentSum.h" -#include "AmpGen/Integrator.h" -#include "AmpGen/MinuitParameterSet.h" -#include "AmpGen/Projection.h" -#include "AmpGen/Utilities.h" -#include "AmpGen/EventList.h" - -#include -#include -#include -#include -#include - -namespace AmpGen -{ - void perAmplitudePlot(const EventList& evts, const Projection& projection, const CoherentSum& pdf); - - template - std::array getNorms( CoherentSum& fcn, BinnedIntegrator& bid ) - { - std::array normalisations; - for ( unsigned int i = 0; i < NBINS; ++i ) normalisations[i] = Bilinears( fcn.size(), fcn.size() ); - for ( unsigned int i = 0; i < fcn.size(); ++i ) { - for ( unsigned int j = i; j < fcn.size(); ++j ) { - bid.addIntegral( fcn[i].amp, fcn[j].amp, [i, j, &normalisations]( const auto& val ) - { - for ( unsigned int bin = 0; bin < NBINS; ++bin ) { - normalisations[bin].set( i, j, val[bin] ); - if ( i != j ) normalisations[bin].set( j, i, std::conj( val[bin] ) ); - } - } ); - } - } - bid.flush(); - return normalisations; - } - - template - std::array getNorms( IncoherentSum& fcn, BinnedIntegrator& bid ) - { - std::array normalisations; - for ( unsigned int i = 0; i < NBINS; ++i ) normalisations[i] = Bilinears( fcn.size(), fcn.size() ); - for ( unsigned int i = 0; i < fcn.size(); ++i ) { - bid.addIntegral( fcn[i].amp, fcn[i].amp, [i, &normalisations]( const auto& val ) { - for ( unsigned int bin = 0; bin < NBINS; ++bin ) normalisations[bin].set( i, 0, val[bin] ); - } ); - } - bid.flush(); - return normalisations; - } - - template - TH1D* plotWithError( EventList& events, FCN& fcn, const Projection& projection, const std::string& prefix, - LinearErrorPropagator& linProp, const std::function& selection = nullptr ) - { - BinnedIntegrator bid( &events ); - if ( selection != nullptr ) bid.setSlice( selection ); - bid.setView( projection.binFunctor() ); - TH1D* plot = projection.plot(); - plot->SetName( ( prefix + plot->GetName() ).c_str() ); - auto normalisations = getNorms( fcn, bid ); - auto vectorBinFunctor = [&normalisations, &fcn, &bid] { - fcn.transferParameters(); - bid.update( fcn, normalisations ); - std::vector values(NBINS); - double total = 0; - for ( size_t bin = 0; bin < NBINS; ++bin ) { - values[bin] = fcn.norm( normalisations[bin] ); - total += values[bin]; - } - for ( size_t bin = 0; bin < NBINS; ++bin ) values[bin] /= total; - return values; - }; - auto values = vectorBinFunctor(); - auto errors = linProp.getVectorError( vectorBinFunctor, NBINS ); - for ( size_t bin = 0; bin < NBINS; ++bin ) { - plot->SetBinContent( bin + 1, values[bin] ); - plot->SetBinError( bin + 1, errors[bin] ); - } - return plot; - } - - template - std::vector bandPlot( EventList& events, const std::string& prefix, FCN& fcn, LinearErrorPropagator& linProp ) - { - std::vector plots; - auto axes = events.eventType().defaultProjections( NBINS ); - for ( auto& proj : axes ) { - INFO( "Making plot:" << proj.name() ); - plots.push_back( plotWithError( events, fcn, proj, prefix, linProp ) ); - } - return plots; - } - TGraph* boundary(const AmpGen::EventType& type, - const std::function& p1, - const std::function& p2 ); -} // namespace AmpGen - -#endif diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index 0cc662c728d..308f61833e3 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -15,12 +15,14 @@ #include "AmpGen/CompiledExpression.h" #include "AmpGen/EventList.h" #include "AmpGen/EventType.h" -#include "AmpGen/Integrator2.h" +#include "AmpGen/Integrator.h" #include "AmpGen/CoherentSum.h" #include "AmpGen/Expression.h" #include "AmpGen/Tensor.h" #include "AmpGen/MinuitParameter.h" +#include "AmpGen/IntegratorSIMD.h" + #include "TMatrixD.h" namespace AmpGen @@ -35,7 +37,17 @@ namespace AmpGen class PolarisedSum { public: - typedef Integrator2 integrator; + #if ENABLE_AVX2 + using EventList_type = EventListSIMD; + using Integrator_type= IntegratorSIMD; + using complex_v = AVX2::complex_t; + using float_v = AVX2::float_t; + #else + using EventList_type = EventList; + using Integrator_type = Integrator; + using complex_v = complex_t; + using float_v = real_t; + #endif PolarisedSum() = default; PolarisedSum(const EventType&, MinuitParameterSet&, const std::vector& = {}); @@ -53,7 +65,7 @@ namespace AmpGen Expression probExpression(const Tensor&, const std::vector&, DebugSymbols* = nullptr) const; size_t size() const; real_t norm() const; - complex_t norm(const size_t&, const size_t&, integrator* = nullptr); + complex_t norm(const size_t&, const size_t&, Integrator* = nullptr); inline real_t operator()(const Event& evt) const { return m_weight * prob_unnormalised(evt) / m_norm; } real_t prob_unnormalised(const Event&) const; real_t prob(const Event&) const; @@ -74,7 +86,7 @@ namespace AmpGen std::vector m_pVector = {}; bool m_verbosity = {0}; bool m_debug = {0}; - integrator m_integrator; + Integrator m_integrator; std::vector m_norms; EventType m_eventType; std::string m_prefix = ""; @@ -83,7 +95,7 @@ namespace AmpGen AmplitudeRules m_rules; std::pair m_dim; std::vector> m_matrixElements; - CompiledExpression m_probExpression; + CompiledExpression m_probExpression; std::vector> indexProduct(const std::vector>&, const std::vector&) const; std::vector polarisations(const std::string&) const ; diff --git a/AmpGen/ProfileClock.h b/AmpGen/ProfileClock.h index b625b72e55e..2b334861f9c 100644 --- a/AmpGen/ProfileClock.h +++ b/AmpGen/ProfileClock.h @@ -21,11 +21,31 @@ namespace AmpGen{ }; template - double Profile( const FCN& fcn ){ + double Profile( const FCN& fcn, const std::string& name ="" ){ ProfileClock t; for( size_t i = 0 ; i < N; ++i ) fcn(); t.stop(); - INFO( typeof() << " " << t/double(N) << "[ms] per iteration" ); + INFO( (name == "" ? typeof() : name ) << " " << t/double(N) << "[ms] per iteration" ); + return t; + } + template + double ProfileWithStat( const FCN& fcn, const std::string& name ="" ){ + double t = 0; + double t2 = 0; + double tmin = 1e9; + double tmax = 0; + for( size_t i = 0 ; i < N; ++i ){ + ProfileClock pi; + fcn(); + pi.stop(); + t += pi; + t2 += pi*pi; + tmin = pi < tmin ? pi : tmin; + tmax = pi > tmax ? pi : tmax; + } + t /= double(N); + t2 = sqrt( t2 / double(N) - t*t); + INFO( (name == "" ? typeof() : name ) << " " << t << " ± " << t2 << "[ms] per iteration << [" << tmin << ", " << tmax << "]" ); return t; } diff --git a/AmpGen/Projection.h b/AmpGen/Projection.h index 53730e4de3e..2a2481693fa 100644 --- a/AmpGen/Projection.h +++ b/AmpGen/Projection.h @@ -31,13 +31,13 @@ namespace AmpGen const std::string& xAxisTitle, const size_t& nBins, const double& min, const double& max, const std::string& units = "" ); const std::string name() const; - template TH1D* operator()(const EventList& evt, const ARGS... args) const + template TH1D* operator()(const eventlist_type& evts, const ARGS... args) const { - return projInternal(evt, ArgumentPack(args...) ); + return projInternal(evts, ArgumentPack(args...) ); } - template std::tuple, THStack*> operator()(const EventList& evt, const KeyedView& weightFunction, const ARGS... args ) const + template std::tuple, THStack*> operator()(const eventlist_type& evts, const KeyedView& weightFunction, const ARGS... args ) const { - return projInternal(evt, weightFunction, ArgumentPack(args...) ); + return projInternal(evts, weightFunction, ArgumentPack(args...) ); } double operator()( const Event& evt ) const; @@ -49,8 +49,10 @@ namespace AmpGen friend class Projection2D; private: - TH1D* projInternal(const EventList&, const ArgumentPack&) const; - std::tuple, THStack*> projInternal(const EventList&, const KeyedView&, const ArgumentPack&) const; + template + TH1D* projInternal(const eventlist_type&, const ArgumentPack&) const; + template + std::tuple, THStack*> projInternal(const eventlist_type&, const KeyedView&, const ArgumentPack&) const; std::function m_func; std::string m_name = {""}; std::string m_xAxisTitle = {""}; @@ -81,6 +83,7 @@ namespace AmpGen DECLARE_ARGUMENT(Prefix , std::string); DECLARE_ARGUMENT(Norm , double); DECLARE_ARGUMENT(AddTo , THStack*); + DECLARE_ARGUMENT(AutoWrite , bool); } } // namespace AmpGen diff --git a/AmpGen/RecursivePhaseSpace.h b/AmpGen/RecursivePhaseSpace.h index 73cb08f8bbe..bf71534a906 100644 --- a/AmpGen/RecursivePhaseSpace.h +++ b/AmpGen/RecursivePhaseSpace.h @@ -47,7 +47,7 @@ namespace AmpGen void print( const size_t& offset = 0 ) const; void setRandom( TRandom* rand ); - Event makeEvent( const size_t& cacheSize = 0 ); + Event makeEvent(); size_t size() const; EventType eventType() const ; diff --git a/AmpGen/SumPDF.h b/AmpGen/SumPDF.h index 3388560266d..0bf34fa827e 100644 --- a/AmpGen/SumPDF.h +++ b/AmpGen/SumPDF.h @@ -8,6 +8,11 @@ #include "AmpGen/LiteSpan.h" #include +#if ENABLE_AVX2 + #include "AmpGen/simd/avx2_types.h" + #include "AmpGen/simd/utils.h" +#endif + namespace AmpGen { class EventList; @@ -49,18 +54,42 @@ namespace AmpGen SumPDF( const pdfTypes&... pdfs ) : m_pdfs( std::tuple( pdfs... ) ) {} /// Returns negative twice the log-likelihood for this PDF and the given dataset. + double getVal() { - double LL = 0; - for_each( m_pdfs, []( auto& f ) { f.prepare(); } ); - #pragma omp parallel for reduction( +: LL ) - for ( unsigned int i = 0; i < m_events->size(); ++i ) { - auto prob = ((*this))(( *m_events)[i] ); - LL += log(prob); + if constexpr( std::is_same::value ) + { + double LL = 0; + for_each( m_pdfs, []( auto& f ) { f.prepare(); } ); + #pragma omp parallel for reduction( +: LL ) + for ( unsigned int i = 0; i < m_events->size(); ++i ) { + auto prob = ((*this))(( *m_events)[i] ); + LL += log(prob); + } + return -2 * LL; + } + #if ENABLE_AVX2 + if constexpr( std::is_same::value ) + { + float_v LL = 0.f; + for_each( m_pdfs, []( auto& f ) { f.prepare(); } ); + #pragma omp parallel for reduction( +: LL ) + for ( unsigned int block = 0; block < m_events->nBlocks(); ++block ) { + LL += log(this->operator()(m_events->block(block), block)); + } + return -2 * utils::sum_elements(LL); } - return -2 * LL; + #endif + } + /// Returns the probability for the given event. + #if ENABLE_AVX2 + float_v operator()( const float_v* evt , const unsigned block) + { + float_v prob = 0.f; + for_each( this->m_pdfs, [&prob, &evt,block]( const auto& f ) { prob += f(evt, block); } ); + return prob; } - + #endif /// Returns the probability for the given event. double operator()( const eventValueType& evt ) { diff --git a/AmpGen/ThreeBodyCalculators.h b/AmpGen/ThreeBodyCalculators.h index 887baf2b958..d7b24724dd4 100644 --- a/AmpGen/ThreeBodyCalculators.h +++ b/AmpGen/ThreeBodyCalculators.h @@ -18,12 +18,12 @@ namespace AmpGen struct PartialWidth { CoherentSum fcs; DalitzIntegrator integrator; - CompiledExpression< std::complex, const real_t*, const real_t* > totalWidth; + CompiledExpression totalWidth; EventType type; - std::vector, const real_t*, const real_t*>> partialWidths; + std::vector> partialWidths; double getWidth( const double& m ); PartialWidth( const EventType& type, MinuitParameterSet& mps ); - Expression spinAverageMatrixElement( const std::vector>>& elements, + Expression spinAverageMatrixElement( const std::vector >& elements, DebugSymbols* msym ); }; Expression calculateSAME( const std::string& particle ); diff --git a/AmpGen/TreePhaseSpace.h b/AmpGen/TreePhaseSpace.h index f9c3f33922a..bca2cd1da5c 100644 --- a/AmpGen/TreePhaseSpace.h +++ b/AmpGen/TreePhaseSpace.h @@ -51,7 +51,7 @@ namespace AmpGen void generate(); void print(const unsigned& offset = 0) const; void place(Event& event); - Event event(const unsigned& eventSize, const unsigned& cacheSize=0); + Event event(const unsigned& eventSize); void generateFullEvent(); void setRhoMax(); void setRandom(TRandom3* rnd); @@ -82,7 +82,7 @@ namespace AmpGen TreePhaseSpace(const std::vector& decayChains, const EventType& type, TRandom* rndm = nullptr); void setRandom( TRandom* rand ); - Event makeEvent( const unsigned& cacheSize = 0 ); + Event makeEvent(); size_t size() const; EventType eventType() const ; double genPdf( const Event& event) const ; diff --git a/AmpGen/Utilities.h b/AmpGen/Utilities.h index 929c55c558f..791ae437a37 100644 --- a/AmpGen/Utilities.h +++ b/AmpGen/Utilities.h @@ -161,13 +161,10 @@ namespace AmpGen { } return total; } - template std::function - arrayToFunctor( const std::vector& values, const container_type* container ) + template std::function + arrayToFunctor( const std::vector& values) { - return [container, values](const typename container_type::value_type& event) -> return_type { - int addr = &event - &container->at(0); - return *(values.data() + addr); }; + return [values](const contained_type& event) -> return_type {return *(values.data() + event.index()); }; } template diff --git a/Standalone.cmake b/Standalone.cmake index f96ab83bb78..a0047390f44 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -13,6 +13,7 @@ if( NOT "${CMAKE_CXX_STANDARD}" ) endif() SET(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") +SET(ENABLE_AVX2 TRUE CACHE BOOL "ENABLE_AVX2") set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -137,18 +138,25 @@ endif() target_compile_definitions(AmpGen PRIVATE "AMPGENROOT_CMAKE=\"${CMAKE_BINARY_DIR}/bin\"" + "AMPGENROOT=\"${PROJECT_SOURCE_DIR}\"" "AMPGEN_CXX=\"${AMPGEN_CXX}\"" "USE_OPENMP=\"${USE_OPENMP}\"" $<$:DEBUGLEVEL=1> $<$:TRACELEVEL=1>) + target_compile_options(AmpGen INTERFACE -Wall -Wextra -Wpedantic -g3 -Wno-unused-parameter -Wno-unknown-pragmas - -march=native - $<$:-Ofast>) + $<$:-O3>) + +if( ENABLE_AVX2 ) + message(STATUS "Enabling AVX2...") + target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX2=1") + target_compile_options(AmpGen PUBLIC -march=native -ftree-vectorize -mavx2 -DHAVE_AVX2_INSTRUCTIONS) +endif() if("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" ) target_link_libraries(AmpGen PUBLIC stdc++) diff --git a/apps/ConvertToSourceCode.cpp b/apps/ConvertToSourceCode.cpp index 7e476408153..c753204bb7c 100644 --- a/apps/ConvertToSourceCode.cpp +++ b/apps/ConvertToSourceCode.cpp @@ -16,11 +16,12 @@ #include "AmpGen/Particle.h" #include "AmpGen/ParticlePropertiesList.h" #include "AmpGen/AddCPConjugate.h" - +#include "AmpGen/simd/utils.h" #include "TRandom3.h" using namespace AmpGen; +/* template void create_integration_tests(T& pdf, const EventType& type, @@ -62,12 +63,13 @@ void create_integration_tests(T& pdf, unit_tests << "};" << std::endl; unit_tests << " auto expr = make_expression(p.getExpression(), p.decayDescriptor(), type.getEventFormat(), mps);" << std::endl; unit_tests << " auto eval = expr(event);" << std::endl; - unit_tests << " BOOST_TEST( std::real(eval) == " << std::real(value)<< ", boost::test_tools::tolerance(1e-6)) ;" << std::endl; - unit_tests << " BOOST_TEST( std::imag(eval) == " << std::imag(value)<< ", boost::test_tools::tolerance(1e-6)) ;" << std::endl; + unit_tests << " BOOST_TEST( std::real(eval) == " << std::real(utils::get<0>(value))<< ", boost::test_tools::tolerance(1e-6)) ;" << std::endl; + unit_tests << " BOOST_TEST( std::imag(eval) == " << std::imag(utils::get<0>(value))<< ", boost::test_tools::tolerance(1e-6)) ;" << std::endl; unit_tests << "}\n\n"; } unit_tests.close(); } +*/ template void generate_source(T& pdf, EventList& normEvents, const std::string& sourceFile, MinuitParameterSet& mps, const double& sf) { @@ -130,7 +132,7 @@ int main( int argc, char** argv ) if( type == "CoherentSum" ){ CoherentSum sig( eventType, MPS, "" ); generate_source( sig, phspEvents, sourceFile, MPS, safetyFactor ); - create_integration_tests(sig, eventType, MPS, {phspEvents[15]}, sourceFile ); + //create_integration_tests(sig, eventType, MPS, {phspEvents[15]}, sourceFile ); } if( type == "PolarisedSum" ){ PolarisedSum sig( eventType, MPS ); diff --git a/apps/Debugger.cpp b/apps/Debugger.cpp index a440aab9247..29a1c2346a5 100644 --- a/apps/Debugger.cpp +++ b/apps/Debugger.cpp @@ -89,10 +89,12 @@ int main( int argc, char** argv ) EventList accepted = infile == "" ? EventList( eventType ) : EventList( infile, eventType ); std::string input_units = NamedParameter("Units","GeV"); - if( input_units == "MeV" && infile != "") accepted.transform([](auto& event){ for( int i = 0;i<16;++i) event[i]/=1000; } ); + if( input_units == "MeV" && infile != "") accepted.transform([](auto& event){ for( unsigned i = 0;i< event.size();++i) event[i]/=1000; } ); if( infile == "" ){ - Event evt = PhaseSpace( eventType, rndm ).makeEvent(); - accepted.push_back(evt); + for( unsigned i = 0 ; i != 16; ++i ){ + Event evt = PhaseSpace( eventType, rndm ).makeEvent(); + accepted.push_back(evt); + } } accepted[0].print(); diff --git a/apps/Fitter.cpp b/apps/Fitter.cpp index a1dedbb40b7..5159a789cd7 100644 --- a/apps/Fitter.cpp +++ b/apps/Fitter.cpp @@ -28,13 +28,20 @@ #include "AmpGen/ThreeBodyCalculators.h" #include "AmpGen/Utilities.h" #include "AmpGen/Generator.h" -#include "AmpGen/Plots.h" #ifdef _OPENMP #include #include #endif +#if ENABLE_AVX2 + #include "AmpGen/EventListSIMD.h" + using EventList_type = AmpGen::EventListSIMD; +#else + #include "AmpGen/EventList.h" + using EventList_type = AmpGen::EventList; +#endif + #include "TFile.h" #include "TRandom3.h" @@ -60,15 +67,6 @@ void randomizeStartingPoint( MinuitParameterSet& MPS, TRandom3& rand, bool Splin } } -unsigned int count_amplitudes( const AmpGen::MinuitParameterSet& mps ) -{ - unsigned int counter = 0; - for ( auto param = mps.cbegin(); param != mps.cend(); ++param ) { - if ( ( *param )->name().find( "_Re" ) != std::string::npos ) counter++; - } - return counter; -} - template void addExtendedTerms( Minimiser& mini, SIGPDF& pdf, MinuitParameterSet& mps ) { @@ -219,10 +217,9 @@ int main( int argc, char* argv[] ) const std::string cut = NamedParameter( "Cut", "1" ); const std::string simCut = NamedParameter( "SimCut", "1" ); bool BAR = NamedParameter("Bar",false); - size_t defaultCacheSize = count_amplitudes( MPS ); - EventList events( dataFile, !BAR ? evtType : evtType.conj() , CacheSize(defaultCacheSize), Filter(cut) ); - EventList eventsMC = mcFile == "" ? EventList( evtType) : EventList( mcFile, !BAR ? evtType : evtType.conj() , CacheSize(defaultCacheSize), Filter(simCut) ) ; + EventList events( dataFile, !BAR ? evtType : evtType.conj() , Filter(cut) ); + EventList eventsMC = mcFile == "" ? EventList( evtType) : EventList( mcFile, !BAR ? evtType : evtType.conj(), Filter(simCut) ) ; auto scale_transform = [](auto& event){ for( size_t x = 0 ; x < event.size(); ++x ) event[x] /= 1000.; }; if( NamedParameter("Units", "GeV").getVal() == "MeV") { diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp index 8fbcf63695e..48878c4a5a3 100644 --- a/examples/QcGenerator.cpp +++ b/examples/QcGenerator.cpp @@ -50,7 +50,7 @@ struct DTEvent AmpGen::Event signal; AmpGen::Event tag; double prob; - DTEvent() : signal(0,0,0), tag(0,0,0) {}; + DTEvent() : signal(0,0), tag(0,0) {}; DTEvent( const AmpGen::Event& signal, const AmpGen::Event& tag ) : signal(signal), tag(tag) {}; void set( const AmpGen::Event& s1, const AmpGen::Event& s2 ) { signal.set(s1); tag.set(s2); }; void invertParity(){ @@ -143,7 +143,7 @@ template class Psi3770 { { double n1(0), n2(0), zR(0), zI(0); auto normEvents = Generator(type).generate(m_blockSize); -#pragma omp parallel for reduction(+:zR,zI,n1,n2) + #pragma omp parallel for reduction(+:zR,zI,n1,n2) for(size_t i = 0; i < m_blockSize; ++i){ auto p1 = t1(normEvents[i]); auto p2 = t2(normEvents[i]); diff --git a/examples/SignalOnlyFitter.cpp b/examples/SignalOnlyFitter.cpp index ce4bc7d5ded..3d3932e573e 100644 --- a/examples/SignalOnlyFitter.cpp +++ b/examples/SignalOnlyFitter.cpp @@ -9,7 +9,6 @@ #include #include "AmpGen/Chi2Estimator.h" -#include "AmpGen/EventList.h" #include "AmpGen/EventType.h" #include "AmpGen/CoherentSum.h" #include "AmpGen/IncoherentSum.h" @@ -27,14 +26,21 @@ #include #endif +#if ENABLE_AVX2 + #include "AmpGen/EventListSIMD.h" + using EventList_type = AmpGen::EventListSIMD; +#else + #include "AmpGen/EventList.h" + using EventList_type = AmpGen::EventList; +#endif + #include #include #include using namespace AmpGen; -template -FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& MPS ); +template FitResult* doFit( PDF&& pdf, EventList_type& data, EventList_type& mc, MinuitParameterSet& MPS ); int main( int argc, char* argv[] ) { @@ -98,12 +104,12 @@ int main( int argc, char* argv[] ) /* Events are read in from ROOT files. If only the filename and the event type are specified, the file is assumed to be in the specific format that is defined by the event type, unless the branches to load are specified in the user options */ - EventList events(dataFile, evtType, Branches(bNames), GetGenPdf(false) ); + EventList_type events(dataFile, evtType, Branches(bNames), GetGenPdf(false) ); /* Generate events to normalise the PDF with. This can also be loaded from a file, which will be the case when efficiency variations are included. Default number of normalisation events is 5 million. */ - EventList eventsMC = intFile == "" ? Generator<>(evtType, &rndm).generate(2e6) : EventList(intFile, evtType, GetGenPdf(true)); + EventList_type eventsMC = intFile == "" ? Generator<>(evtType, &rndm).generate(2.5e6) : EventList_type(intFile, evtType, GetGenPdf(true)); sig.setMC( eventsMC ); @@ -119,19 +125,12 @@ int main( int argc, char* argv[] ) fr->addFractions( fitFractions ); fr->writeToFile( logFile ); - output->cd(); - /* Write out the data plots. This also shows the first example of the named arguments - to functions, emulating python's behaviour in this area */ - - auto plots = events.makeDefaultProjections(PlotOptions::Prefix("Data"), PlotOptions::Bins(100)); - for ( auto& plot : plots ) plot->Write(); - output->Close(); } template -FitResult* doFit( likelihoodType&& likelihood, EventList& data, EventList& mc, MinuitParameterSet& MPS ) +FitResult* doFit( likelihoodType&& likelihood, EventList_type& data, EventList_type& mc, MinuitParameterSet& MPS ) { auto time_wall = std::chrono::high_resolution_clock::now(); auto time = std::clock(); @@ -151,9 +150,9 @@ FitResult* doFit( likelihoodType&& likelihood, EventList& data, EventList& mc, M /* Estimate the chi2 using an adaptive / decision tree based binning, down to a minimum bin population of 15, and add it to the output. */ - Chi2Estimator chi2( data, mc, likelihood.evaluator(&mc), MinEvents(15), Dim(data.eventType().dof()) ); - chi2.writeBinningToFile("chi2_binning.txt"); - fr->addChi2( chi2.chi2(), chi2.nBins() ); + //Chi2Estimator chi2( data, mc, likelihood.evaluator(&mc), MinEvents(15), Dim(data.eventType().dof()) ); + //chi2.writeBinningToFile("chi2_binning.txt"); + //fr->addChi2( chi2.chi2(), chi2.nBins() ); fr->print(); /* Make the plots for the different components in the PDF, i.e. the signal and backgrounds. @@ -163,12 +162,9 @@ FitResult* doFit( likelihoodType&& likelihood, EventList& data, EventList& mc, M auto projections = data.eventType().defaultProjections(100); for( const auto& proj : projections ) { - auto [components, total] = proj(mc, evaluator, PlotOptions::Norm(data.size() ) ); - for( const auto& component : components ) component->Write(); - total->Write(); - auto [signal_components, total_signal_component] = proj(mc, evaluator_per_component, PlotOptions::Norm(data.size()) ); - for( const auto& component : signal_components ) component->Write(); - total_signal_component->Write(); + proj(mc, evaluator, PlotOptions::Norm(data.size()), PlotOptions::AutoWrite() ); + proj(mc, evaluator_per_component, PlotOptions::Prefix("amp"), PlotOptions::Norm(data.size()), PlotOptions::AutoWrite() ); + proj(data, PlotOptions::Prefix("Data") )->Write(); } return fr; } diff --git a/src/ASTResolver.cpp b/src/ASTResolver.cpp index 8732bed9b14..2b6785aba3f 100644 --- a/src/ASTResolver.cpp +++ b/src/ASTResolver.cpp @@ -19,6 +19,7 @@ ASTResolver::ASTResolver(const std::map& evtMap, m_nParameters(0) { m_enable_cuda = NamedParameter("UseCUDA",false); + m_enable_avx = NamedParameter("UseAVX",false); m_enable_compileTimeConstants = NamedParameter("ASTResolver::CompileTimeConstants", false); } diff --git a/src/BinDT.cpp b/src/BinDT.cpp index e6c15149b0d..24a62280198 100644 --- a/src/BinDT.cpp +++ b/src/BinDT.cpp @@ -97,10 +97,11 @@ BinDT::BinDT( const ArgumentPack& args ) } } -BinDT::BinDT( const EventList& events, const ArgumentPack& args ) : BinDT(args) +BinDT::BinDT( const EventList& events, const ArgumentPack& args ) : BinDT(args) { - m_top = makeNodes(events); + makeNodes( events.begin(), events.end() ); } + void BinDT::readFromStream( std::istream& stream ) { std::map>> nodes; @@ -368,16 +369,3 @@ void BinDT::Decision::visit( const std::function& visit_fun m_right->visit( visit_function ); } -std::shared_ptr BinDT::makeNodes( const EventList& events ) -{ - std::vector data( m_dim * events.size() ); - std::vector addresses( events.size() ); - size_t counter = 0; - for ( auto& evt : events ) { - auto val = m_functors( evt ); - for ( unsigned int i = 0; i < m_dim; ++i ) data[m_dim * counter + i] = val[i]; - addresses[counter] = &( data[m_dim * counter] ); - counter++; - } - return makeNodes( addresses ); -} diff --git a/src/Chi2Estimator.cpp b/src/Chi2Estimator.cpp index 500210f0489..a94b04fdc67 100644 --- a/src/Chi2Estimator.cpp +++ b/src/Chi2Estimator.cpp @@ -56,10 +56,11 @@ void Chi2Estimator::doChi2( const EventList& dataEvents, const EventList& mcEv j++; } j = 0; - for ( auto& evt : mcEvents ) { + for ( auto& evt : mcEvents ) + { if ( j % 1000000 == 0 && j != 0 ) INFO( "Binned " << j << " sim. events" ); double w = fcn( evt ) * evt.weight() / evt.genPdf(); - mc[m_binning.getBinNumber( evt )].add( w ); + mc[m_binning.getBinNumber(evt)].add( w ); total_int_weight += w; j++; } diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 3bc4b612121..9ad5a6629c8 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -25,6 +25,7 @@ #include "AmpGen/CompilerWrapper.h" #include "AmpGen/ThreadPool.h" #include "AmpGen/ProfileClock.h" +#include "AmpGen/simd/utils.h" #ifdef _OPENMP #include @@ -34,13 +35,13 @@ using namespace AmpGen; CoherentSum::CoherentSum() = default; CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, const std::string& prefix ) - : m_rules(mps) - , m_evtType (type) - , m_printFreq (NamedParameter( "CoherentSum::PrintFrequency", 100) ) - , m_dbThis (NamedParameter( "CoherentSum::Debug" , false)) - , m_verbosity (NamedParameter( "CoherentSum::Verbosity" , 0) ) - , m_objCache (NamedParameter("CoherentSum::ObjectCache" ,"") ) - , m_prefix (prefix) + : m_rules (mps) + , m_evtType (type) + , m_printFreq(NamedParameter( "CoherentSum::PrintFrequency", 100) ) + , m_dbThis (NamedParameter( "CoherentSum::Debug" , false)) + , m_verbosity(NamedParameter( "CoherentSum::Verbosity" , 0) ) + , m_objCache (NamedParameter("CoherentSum::ObjectCache" ,"") ) + , m_prefix (prefix) { auto amplitudes = m_rules.getMatchingRules( m_evtType, prefix); if( amplitudes.size() == 0 ){ @@ -53,21 +54,12 @@ CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, ThreadPool tp(nThreads); for(size_t i = 0; i < m_matrixElements.size(); ++i){ tp.enqueue( [i,this,&mps,&litudes]{ - m_matrixElements[i] = TransitionMatrix( amplitudes[i].first, amplitudes[i].second, mps, this->m_evtType.getEventFormat(), this->m_dbThis); + m_matrixElements[i] = TransitionMatrix( amplitudes[i].first, amplitudes[i].second, mps, this->m_evtType.getEventFormat(), this->m_dbThis); CompilerWrapper().compile( m_matrixElements[i].amp, this->m_objCache); } ); } m_isConstant = false; } -void updateCache(EventList* events, TransitionMatrix& me, const size_t& sizeMax) -{ - if ( me.addressData == 999 ) - { - if( events->at(0).cacheSize() <= sizeMax) events->resizeCache(sizeMax); - me.addressData = events->registerExpression( me.amp ); - } - events->updateCache(me.amp, me.addressData); -} void CoherentSum::prepare() { @@ -75,22 +67,38 @@ void CoherentSum::prepare() transferParameters(); std::vector changedPdfIndices; ProfileClock clockEval; - bool print = false; + if( m_prepareCalls == 0 && m_events != nullptr ){ + m_events->reserveCache(m_matrixElements.size()); + for( auto& me : m_matrixElements ) me.addressData = m_events->registerExpression( me.amp ); + } + if( m_prepareCalls == 0 ) m_integrator.allocate( m_matrixElements ); for ( size_t i = 0; i < m_matrixElements.size(); ++i ) { m_matrixElements[i].amp.prepare(); if ( m_prepareCalls != 0 && !m_matrixElements[i].amp.hasExternalsChanged() ) continue; - if ( m_events != nullptr ) updateCache( m_events, m_matrixElements[i], m_matrixElements.size() ); - m_integrator.prepareExpression( m_matrixElements[i].amp ); + if ( m_events != nullptr ) m_events->updateCache( m_matrixElements[i].amp, m_matrixElements[i].addressData ); + m_integrator.prepareExpression(m_matrixElements[i].amp ); changedPdfIndices.push_back(i); m_matrixElements[i].amp.resetExternals(); - print = true; } clockEval.stop(); ProfileClock clockIntegral; if ( m_integrator.isReady()) updateNorms( changedPdfIndices ); else if ( m_verbosity ) WARNING( "No simulated sample specified for " << this ); m_norm = norm(); - if ( m_verbosity && print ) { + if ( m_prepareCalls == 0 ){ + INFO( "Norm: " << m_norm ); + for(unsigned i = 0 ; i != m_matrixElements.size() ; ++i ){ + for(unsigned j = 0 ; j != m_matrixElements.size() ; ++j ){ + if( std::isnan( std::real(m_normalisations(i,j) )) || std::isnan( std::imag(m_normalisations(i,j))) ) + ERROR("Norm: " << m_matrixElements[i].name() << " " << m_matrixElements[j].name() << " is ill-posed!"); + } + } + // INFO( m_normalisations.get(0,0) << " " + // << m_normalisations.get(1,0) << " " + // << m_normalisations.get(0,1) << " " + // << m_normalisations.get(2,2) ); + } + if ( m_verbosity && changedPdfIndices.size() !=0 ) { clockIntegral.stop(); INFO( "Time Performance: " << "Eval = " << clockEval << " ms" @@ -121,17 +129,18 @@ void CoherentSum::debug( const Event& evt, const std::string& nameMustContain ) for ( auto& me : m_matrixElements ) { auto A = me(evt); INFO( std::setw(70) << me.decayTree.uniqueString() - << " A = [ " << std::real(A) << " " << std::imag(A) - << " ] g = [ "<< std::real(me.coupling()) << " " << std::imag(me.coupling()) << " ] " + << " A = [ " << utils::get(A.real()) << " " << utils::get(A.imag()) + << " ] g = [ "<< me.coupling().real() << " " << me.coupling().imag() << " ] " + << m_events->cache( evt.index(), me.addressData ) << me.decayTree.CP() ); - if( m_dbThis ) me.amp.debug( evt.address() ); + // if( m_dbThis ) me.amp.debug( evt.address() ); } - else - for ( auto& me : m_matrixElements ) - if ( me.amp.name().find( nameMustContain ) != std::string::npos ) me.amp.debug( evt.address() ); - if( evt.cacheSize() != 0 ) INFO( "Pdf = " << prob_unnormalised( evt ) ); - INFO( "A(x) = " << getVal(evt) ); + //else + // for ( auto& me : m_matrixElements ) + // if ( me.amp.name().find( nameMustContain ) != std::string::npos ) me.amp.debug( evt.address() ); + // if( evt.cacheSize() != 0 ) INFO( "Pdf = " << prob_unnormalised( evt ) ); + INFO( "A(x) = " << getVal(evt) << " without cache: " << getValNoCache(evt) ); } std::vector CoherentSum::fitFractions(const LinearErrorPropagator& linProp) @@ -194,11 +203,11 @@ void CoherentSum::generateSourceCode(const std::string& fname, const double& nor Expression this_amplitude = p.coupling() * Function( programatic_name( p.amp.name() ) + "_wParams", {event} ); amplitude = amplitude + ( p.decayTree.finalStateParity() == 1 ? 1 : pa ) * this_amplitude; } - stream << CompiledExpression< std::complex, const double*, const int&>( amplitude , "AMP" ) << std::endl; - stream << CompiledExpression< double, const double*, const int&>(fcn::norm(amplitude) / normalisation, "FCN" ) << std::endl; + stream << CompiledExpression(const double*, const int&)>( amplitude , "AMP" ) << std::endl; + stream << CompiledExpression(fcn::norm(amplitude) / normalisation, "FCN" ) << std::endl; if( includePythonBindings ){ - stream << CompiledExpression< unsigned int >( m_matrixElements.size(), "matrix_elements_n" ) << std::endl; - stream << CompiledExpression< double > ( normalisation, "normalization") << std::endl; + stream << CompiledExpression( m_matrixElements.size(), "matrix_elements_n" ) << std::endl; + stream << CompiledExpression( normalisation, "normalization") << std::endl; stream << "extern \"C\" const char* matrix_elements(int n) {\n"; for ( size_t i = 0; i < m_matrixElements.size(); i++ ) { @@ -228,21 +237,6 @@ void CoherentSum::generateSourceCode(const std::string& fname, const double& nor stream << ( i == size() - 1 ? ";" : " +" ) << "\n"; } stream << " out[i] = std::norm(amplitude) / " << normalisation << ";\n }\n}\n"; - stream << "extern \"C\" void FCN_mt(double* out, double* events, unsigned int size, int parity, double* amps){\n"; - stream << " unsigned int n = std::thread::hardware_concurrency();\n"; - stream << " unsigned int batch_size = size / n;\n"; - stream << " std::vector threads;\n"; - stream << " for(size_t i=0; im_events )[0].size() - << ", len, parity, amps);\n"; - stream << " }\n"; - stream << " for(auto &thread : threads)\n"; - stream << " thread.join();\n"; - stream << "}\n\n"; stream << "extern \"C\" double coefficients( int n, int which, int parity){\n"; for ( size_t i = 0; i < size(); i++ ) { @@ -260,18 +254,10 @@ void CoherentSum::generateSourceCode(const std::string& fname, const double& nor complex_t CoherentSum::getValNoCache( const Event& evt ) const { - return std::accumulate( m_matrixElements.begin(), - m_matrixElements.end(), - complex_t(0,0), - [&evt]( auto& a, auto& b ){ return a + b.coefficient * b(evt);} ); -} - -complex_t CoherentSum::getValNoCache(const Event& evt, const size_t& offset) const -{ - return std::accumulate( m_matrixElements.begin(), + return utils::get<0>( complex_v(std::accumulate( m_matrixElements.begin(), m_matrixElements.end(), - complex_t(0,0), - [&evt,&offset]( auto& a, auto& b ){ return a + b.coefficient * b(evt, offset);} ); + complex_v(0,0), + [&evt]( const auto& a, const auto& b ){ return a + b.coefficient * b(evt);} )) ); } void CoherentSum::reset( bool resetEvents ) @@ -281,22 +267,23 @@ void CoherentSum::reset( bool resetEvents ) for ( auto& mE : m_matrixElements ) mE.addressData = 999; if ( resetEvents ){ m_events = nullptr; - m_integrator = Integrator2(); + m_integrator = Integrator_type(); } } -void CoherentSum::setEvents( EventList& list ) +void CoherentSum::setEvents( EventList_type& list ) { if ( m_verbosity ) INFO( "Setting event list with:" << list.size() << " events for " << this ); reset(); m_events = &list; } -void CoherentSum::setMC( EventList& sim ) + +void CoherentSum::setMC( EventList_type& sim ) { if ( m_verbosity ) INFO( "Setting norm. event list with:" << sim.size() << " events for " << this ); reset(); - m_integrator = Integrator2(&sim); + m_integrator = Integrator_type( &sim ); } real_t CoherentSum::norm() const @@ -333,7 +320,7 @@ void CoherentSum::printVal(const Event& evt) { for ( auto& mE : m_matrixElements ) { unsigned int address = mE.addressData; - std::cout << mE.decayTree.decayDescriptor() << " = " << mE.coefficient << " x " << evt.getCache( address ) + std::cout << mE.decayTree.decayDescriptor() << " = " << mE.coefficient << " x " << m_events->cache( evt.index(), address ) << " address = " << address << " " << mE( evt ) << std::endl; if( mE.coupling.size() != 1 ){ std::cout << "CouplingConstants: " << std::endl; @@ -343,56 +330,57 @@ void CoherentSum::printVal(const Event& evt) } } -std::vector CoherentSum::cacheAddresses( const EventList& evts ) const -{ - std::vector addresses; - std::transform( m_matrixElements.begin(), m_matrixElements.end(), std::back_inserter(addresses), - [&evts](auto& it ){ return evts.getCacheIndex( it.amp ) ; } ); - return addresses; -} - complex_t CoherentSum::getVal( const Event& evt ) const { - complex_t value( 0., 0. ); - for ( auto& mE : m_matrixElements ) { - value += mE.coefficient * evt.getCache( mE.addressData ); + complex_v value( 0., 0. ); + for ( const auto& mE : m_matrixElements ) { + value = value + mE.coefficient * m_events->cache( evt.index(), mE.addressData ); } + #if ENABLE_AVX2 + return value.at(evt.index() % float_v::size); + #else return value; + #endif } -complex_t CoherentSum::getVal( const Event& evt, const std::vector& cacheAddresses ) const +#if ENABLE_AVX2 +float_v CoherentSum::operator()( const float_v* /*evt*/, const unsigned block ) const { - complex_t value( 0., 0. ); - for ( size_t i = 0; i < m_matrixElements.size(); ++i ) - value += m_matrixElements[i].coefficient * evt.getCache( cacheAddresses[i] ); - return value; + complex_v value( 0., 0. ); + for ( const auto& mE : m_matrixElements ) { + value = value + mE.coefficient * m_events->cache()[ block * m_events->cacheSize() + mE.addressData ]; + } + return (m_weight/m_norm ) * AVX2::norm( value ); } -std::function CoherentSum::evaluator(const EventList* events) const +#endif + + +std::function CoherentSum::evaluator(const EventList_type* events) const { - if( events != nullptr && events != &this->m_integrator.events() ) + if( events != nullptr && events != m_integrator.events() ) ERROR("Evaluator only working on the integration sample, fix me!"); std::vector address_mapping( size() ); for( const auto& me : m_matrixElements ) address_mapping[me.addressData] = m_integrator.getCacheIndex( me.amp ); - std::vector values( m_integrator.events().size() ); + std::vector values( events->size() ); #ifdef _OPENMP #pragma omp parallel for #endif - for( unsigned int i = 0 ; i != m_integrator.events().size(); ++i ) + for( unsigned int i = 0 ; i != events->size(); ++i ) { complex_t amp = 0; for( unsigned j = 0 ; j != address_mapping.size(); ++j ) amp += m_matrixElements[j].coefficient * this->m_integrator.get(address_mapping[j], i); values[i] = m_weight * std::norm(amp) / m_norm; } - return arrayToFunctor(values, events); + return arrayToFunctor(values); } -KeyedView CoherentSum::componentEvaluator(const EventList* events) const +KeyedView CoherentSum::componentEvaluator(const EventList_type* events) const { - if( events != nullptr && events != &this->m_integrator.events() ) + if( events != nullptr && events != m_integrator.events() ) ERROR("Evaluator only working on the integration sample, fix me!"); - KeyedView rt(*events, m_matrixElements.size() ); + KeyedView rt(*events, m_matrixElements.size() ); std::vector address_mapping(m_matrixElements.size()); for( unsigned i = 0; i != m_matrixElements.size(); ++i ) address_mapping[i] = m_integrator.getCacheIndex( m_matrixElements[i].amp ); @@ -403,14 +391,13 @@ KeyedView CoherentSum::componentEvaluator(const EventList* ev #ifdef _OPENMP #pragma omp parallel for #endif - for( unsigned evt = 0 ; evt != m_integrator.events().size(); ++evt ) + for( unsigned evt = 0 ; evt != events->size(); ++evt ) { complex_t total = 0; for( unsigned j = 0 ; j != m_matrixElements.size(); ++j ){ total += this->m_integrator.get( address_mapping[i], evt ) * m_matrixElements[i].coefficient * std::conj( this->m_integrator.get( address_mapping[j], evt ) * m_matrixElements[j].coefficient ); - } - + } rt(events->at(evt), i) = m_weight * std::real( total ) / m_norm; } } diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index e5a1de4071e..fea41d84a69 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -48,6 +48,10 @@ std::string AmpGen::programatic_name( std::string s ) void CompiledExpressionBase::resolve(const MinuitParameterSet* mps) { if( m_resolver == nullptr ) m_resolver = std::make_shared( m_evtMap, mps ); + if( fcnSignature().find("AVX") != std::string::npos ) { + m_resolver->setEnableAVX(); + enableBatch(); + } m_dependentSubexpressions = m_resolver->getOrderedSubExpressions( m_obj ); for ( auto& sym : m_db ){ auto expressions_for_this = m_resolver->getOrderedSubExpressions( sym.second); @@ -103,7 +107,6 @@ void CompiledExpressionBase::to_stream( std::ostream& stream ) const } } else if( !enable_cuda ){ -// stream << "#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wreturn-type-c-linkage\"\n"; stream << "extern \"C\" " << returnTypename() << " " << progName() << "(" << fcnSignature() << "){\n"; addDependentExpressions( stream , sizeOfStream ); stream << "return " << m_obj.to_string(m_resolver.get()) << ";\n}\n"; @@ -124,6 +127,7 @@ void CompiledExpressionBase::to_stream( std::ostream& stream ) const stream << "}\n"; } if ( m_db.size() != 0 ) addDebug( stream ); + if( m_enableBatch ) compileBatch(stream); } std::ostream& AmpGen::operator<<( std::ostream& os, const CompiledExpressionBase& expression ) diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index 2a2699c7aa1..edfb02d59e6 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -23,6 +23,8 @@ using namespace AmpGen; #ifdef AMPGEN_CXX #pragma message "Using c++ compiler: " AMPGEN_CXX " for JIT" +#pragma message "Using AMPGENROOT: " AMPGENROOT +#pragma message "Using AMPGENROOT_CMAKE: " AMPGENROOT_CMAKE #else #pragma warning "No AMPGEN_CXX for JIT set" #endif @@ -51,6 +53,7 @@ void CompilerWrapper::generateSource( const CompiledExpressionBase& expression, { std::ofstream output( filename ); for ( auto& include : m_includes ) output << "#include <" << include << ">\n"; + if( expression.fcnSignature().find("AVX2") != std::string::npos ) output << "#include \"AmpGen/simd/avx2_types.h\"\n" ; output << expression << std::endl; output.close(); } @@ -130,7 +133,17 @@ void CompilerWrapper::compileSource( const std::string& fname, const std::string { using namespace std::chrono_literals; std::vector compile_flags = NamedParameter("CompilerWrapper::Flags", - {"-Ofast", "--std="+get_cpp_version(),"-march=native"} ); + {"-Ofast", "--std="+get_cpp_version()}); + + #if ENABLE_AVX2 + compile_flags.push_back("-march=native"); + compile_flags.push_back("-mavx2"); + compile_flags.push_back("-DHAVE_AVX2_INSTRUCTIONS"); + compile_flags.push_back( std::string("-I") + AMPGENROOT) ; + #endif + #ifdef _OPENMP + compile_flags.push_back("-fopenmp"); + #endif std::vector argp = { m_cxx.c_str(), "-shared", diff --git a/src/Event.cpp b/src/Event.cpp index 6ffa95df0b5..3f1bf940bd9 100644 --- a/src/Event.cpp +++ b/src/Event.cpp @@ -10,15 +10,11 @@ using namespace AmpGen; -Event::Event( const unsigned& N, const unsigned& cacheSize) : - m_event(N), - m_cache(cacheSize) { - } +Event::Event( const unsigned& N) : + m_event(N) {} -Event::Event( const real_t* data, const unsigned& N, const unsigned& cacheSize) : - m_event(data, data+N), - m_cache(cacheSize) { - } +Event::Event( const real_t* data, const unsigned& N) : + m_event(data, data+N) {} void Event::print() const { unsigned nParticles = m_event.size()/4; @@ -73,11 +69,6 @@ real_t Event::s( const std::vector& indices ) const { } return E*E -px*px - py*py - pz*pz; } -void Event::printCache() const { - for( unsigned int i = 0 ; i < m_cache.size(); ++i){ - INFO("Cache adddress [" << i << "] = " << m_cache[i] ); - } -} void Event::set( const unsigned& i, const std::vector& p ){ for( unsigned j = 0 ; j < 4; ++j) m_event[4*i + j ] = p[j]; @@ -98,6 +89,7 @@ void Event::swap( const unsigned& i , const unsigned& j ) std::memmove( &m_event[4*i], &tmp,sizeof(tmp)); } +/* void Event::setCache(const complex_t& value, const unsigned& pos){ m_cache[pos] = value; } void Event::setCache( const std::vector& value, const unsigned& pos ) { @@ -105,3 +97,4 @@ void Event::setCache( const std::vector& value, const unsigned& pos ) } void Event::resizeCache( const unsigned int& new_size ){ m_cache.resize(new_size); } +*/ diff --git a/src/EventList.cpp b/src/EventList.cpp index c7b90bdd5c5..1ec87d4d377 100644 --- a/src/EventList.cpp +++ b/src/EventList.cpp @@ -62,7 +62,6 @@ void EventList::loadFromTree( TTree* tree, const ArgumentPack& args ) if( tokens.size() != 1 ) m_eventType = EventType( tokens ); INFO("Attempted automatic deduction of eventType: " << m_eventType ); } - auto pdfSize = args.getArg(0).val; auto filter = args.getArg(std::string("")).val; auto getGenPdf = args.getArg(false).val; auto weightBranch = args.getArg(std::string("")).val; @@ -71,7 +70,8 @@ void EventList::loadFromTree( TTree* tree, const ArgumentPack& args ) auto entryList = args.getArg().val; auto eventFormat = m_eventType.getEventFormat( true ); - Event temp( branches.size() == 0 ? eventFormat.size() : branches.size() , pdfSize ); + Event temp( branches.size() == 0 ? eventFormat.size() : branches.size()); + temp.setWeight( 1 ); temp.setGenPdf( 1 ); tree->SetBranchStatus( "*", 0 ); @@ -112,6 +112,7 @@ void EventList::loadFromTree( TTree* tree, const ArgumentPack& args ) for ( unsigned int evt = 0; evt < nEvents; ++evt ) { tr.getEntry( hasEventList ? entryList[evt] : evt ); if( applySym ) symmetriser( temp ); + temp.setIndex( m_data.size() ); m_data.push_back( temp ); } read_time.stop(); @@ -187,7 +188,7 @@ TH2D* EventList::makeProjection( const Projection2D& projection, const ArgumentP void EventList::printCacheInfo( const unsigned int& nEvt ) { for ( auto& ind : m_pdfIndex ) { - INFO( "Cache[" << ind.second << "] = " << ind.first << " = " << at( nEvt ).getCache( ind.second ) ); + INFO( "Cache[" << ind.second << "] = " << ind.first << " = " << cache(nEvt, ind.second ) ); } } @@ -215,8 +216,7 @@ size_t EventList::getCacheIndex( const CompiledExpressionBase& PDF, bool& isRegi void EventList::resetCache() { m_pdfIndex.clear(); - for ( auto evt = begin(); evt != end(); ++evt ) evt->resizeCache( 0 ); - m_lastCachePosition = 0; + m_cache.clear(); } double EventList::integral() const @@ -228,10 +228,7 @@ void EventList::add( const EventList& evts ) { resetCache(); WARNING( "Adding event lists invalidates cache state" ); - for ( auto& evt : evts ) { - m_data.push_back( evt ); - rbegin()->resizeCache( 0 ); - } + for ( auto& evt : evts ) m_data.push_back( evt ); } void EventList::clear() @@ -247,12 +244,7 @@ void EventList::erase(const std::vector::iterator& begin, void EventList::reserveCache(const size_t& size) { - if ( size >= at(0).cacheSize() ) - for (auto& evt : *this) evt.resizeCache(evt.cacheSize() + size); -} - -void EventList::resizeCache(const size_t& newCacheSize ) -{ - for (auto& evt : *this) evt.resizeCache( newCacheSize ); + if ( size * m_data.size() >= m_cache.size() ) + m_cache.reserve( m_data.size() * m_cache.size() ); } diff --git a/src/EventListSIMD.cpp b/src/EventListSIMD.cpp new file mode 100644 index 00000000000..bf7b0ff4864 --- /dev/null +++ b/src/EventListSIMD.cpp @@ -0,0 +1,303 @@ +#if ENABLE_AVX2 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "AmpGen/ArgumentPack.h" +#include "AmpGen/CompiledExpressionBase.h" +#include "AmpGen/EventListSIMD.h" +#include "AmpGen/EventType.h" +#include "AmpGen/MsgService.h" +#include "AmpGen/Projection.h" +#include "AmpGen/TreeReader.h" +#include "AmpGen/Utilities.h" +#include "AmpGen/Event.h" +#include "AmpGen/Types.h" +#include "AmpGen/ProfileClock.h" +#include "AmpGen/simd/utils.h" +using namespace AmpGen; + +EventListSIMD::EventListSIMD( const EventType& type ) : m_eventType( type ), m_eventSize( m_eventType.eventSize() ) {} + +void EventListSIMD::loadFromFile( const std::string& fname, const ArgumentPack& args ) +{ + auto current_file = gFile; + auto tokens = split( fname, ':'); + TTree* tree = nullptr; + if( fname == "" ) FATAL("Filename must be specified to load data"); + if( tokens.size() == 2 ){ + gFile = TFile::Open( tokens[0].c_str(), "READ"); + if( gFile == nullptr ) FATAL("Failed to load file: " << tokens[0] ); + tree = (TTree*)gFile->Get( tokens[1].c_str() ); + } + else { + gFile = TFile::Open( fname.c_str(), "READ"); + if( gFile == nullptr ) FATAL("Failed to load file: " << tokens[0] ); + if( tree == nullptr ) tree = (TTree*)gFile->Get("EventList"); + tree = (TTree*)gFile->Get("DalitzEventList"); + } + if( tree == nullptr ) FATAL( "Failed to load tree from file: " << fname ); + loadFromTree( tree, args ); + gFile->Close(); + gFile = current_file; +} + +void EventListSIMD::loadFromTree( TTree* tree, const ArgumentPack& args ) +{ + ProfileClock read_time; + if( m_eventType.size() == 0 ){ + auto tokens = split( tree->GetTitle(), ' '); + if( tokens.size() != 1 ) setEventType( EventType( tokens ) ); + INFO("Attempted automatic deduction of eventType: " << m_eventType ); + } + auto filter = args.getArg(std::string("")).val; + auto getGenPdf = args.getArg(false).val; + auto weightBranch = args.getArg(std::string("")).val; + auto branches = args.getArg().val; + auto applySym = args.getArg(false).val; + auto entryList = args.getArg().val; + auto eventFormat = m_eventType.getEventFormat( true ); + + Event temp( branches.size() == 0 ? eventFormat.size() : branches.size()); + temp.setWeight( 1 ); + temp.setGenPdf( 1 ); + tree->SetBranchStatus( "*", 0 ); + + TreeReader tr( tree ); + if( branches.size() != 0 ){ + INFO("Branches = [" << vectorToString(branches, ", ") << "]" ); + for ( auto branch = branches.begin(); branch != branches.end(); ++branch ) { + unsigned int pos = std::distance( branches.begin(), branch ); + tr.setBranch( *branch, &(temp[pos]) ); + } + } + else { + for ( auto& branch : eventFormat ){ + tr.setBranch( branch.first, &(temp[branch.second]) ); + } + } + if( getGenPdf ) tr.setBranch( "genPdf", temp.pGenPdf() ); + if( weightBranch != "" ) tr.setBranch( weightBranch, temp.pWeight() ); + if( filter != "" ){ + if( entryList.size() != 0 ){ + WARNING("Specified entry list and filter, will overwrite list with specified selection"); + } + tr.prepare(); + tree->Draw(">>evtList", filter.c_str() ); + TEventList* evtList = (TEventList*)gDirectory->Get("evtList"); + for( int i = 0 ; i < evtList->GetN(); ++i ) entryList.push_back( evtList->GetEntry(i) ); + } + bool hasEventList = entryList.size() != 0; + m_nEvents = hasEventList ? entryList.size() : tree->GetEntries(); + auto aligned_size = utils::aligned_size(m_nEvents); + std::array buffer; + + m_nBlocks = aligned_size / float_v::size; + m_data.resize( m_nBlocks * m_eventSize ); + m_weights.resize( m_nBlocks ); + m_genPDF.resize( m_nBlocks ); + auto symmetriser = m_eventType.symmetriser(); + for ( unsigned int block = 0; block < m_nBlocks; ++block ) + { + for( unsigned k = 0 ; k != float_v::size; ++k ) + { + auto evt = k + block * float_v::size; + if(evt >= m_nEvents ) break; + tr.getEntry( hasEventList ? entryList[evt] : evt ); + if( applySym ) symmetriser( temp ); + buffer[k] = temp; + } + gather( buffer, block ); + } + read_time.stop(); + INFO("Time to read tree = " << read_time << "[ms]; nEntries = " << size() ); +} + + +EventListSIMD::EventListSIMD( const EventList& other ) : EventListSIMD( other.eventType() ) +{ + unsigned aligned_size = utils::aligned_size(other.size()); + m_nBlocks = aligned_size / float_v::size; + m_nEvents = other.size(); + m_data.resize( m_nBlocks * m_eventSize ) ; + m_weights.resize( m_nBlocks ); + m_genPDF.resize ( m_nBlocks ); + for( unsigned evt = 0 ; evt != m_nBlocks; evt ++ ) + { + for( unsigned j = 0 ; j != m_eventSize; ++j ) + m_data[m_eventSize * evt + j] = utils::gather(other, [j](auto& event){ return event[j]; } , evt * float_v::size ); + m_weights[evt] = utils::gather(other, [](auto& event){ return event.weight(); }, evt * float_v::size, 0); + m_genPDF [evt] = utils::gather(other, [](auto& event){ return event.genPdf(); }, evt * float_v::size, 1 ); + } +} + + + +TTree* EventListSIMD::tree( const std::string& name, const std::vector& extraBranches ) const +{ + std::string title = m_eventType.mother(); + for( unsigned i = 0 ; i != m_eventType.size(); ++i ) title += " " + m_eventType[i]; + TTree* outputTree = new TTree( name.c_str(), title.c_str() ); + if ( size() == 0 ) { + ERROR( "Trying to output empty tree" ); + return nullptr; + } + Event tmp = *( begin() ); + double genPdf = 1; + double weight = 1; + auto format = m_eventType.getEventFormat( true ); + + for ( const auto& f : format ) outputTree->Branch( f.first.c_str(), tmp.address( f.second ) ); + // for ( const auto& f : m_extensions ) outputTree->Branch( f.first.c_str(), tmp.address( f.second ) ); + + outputTree->Branch( "genPdf", &genPdf ); + outputTree->Branch( "weight", &weight ); + for ( const auto& evt : *this ) { + tmp = evt; + genPdf = evt.genPdf(); + weight = evt.weight(); + outputTree->Fill(); + } + return outputTree; +} + +std::vector EventListSIMD::makeProjections( const std::vector& projections, const ArgumentPack& args ) +{ + std::vector plots; + for ( const auto& proj : projections ) plots.push_back( makeProjection(proj, args) ); + return plots; +} + +TH1D* EventListSIMD::makeProjection( const Projection& projection, const ArgumentPack& args ) const +{ + auto selection = args.getArg().val; + auto weightFunction = args.getArg().val; + std::string prefix = args.getArg(std::string("")); + auto plot = projection.plot(prefix); + plot->SetLineColor(args.getArg(kBlack).val); + plot->SetMarkerSize(0); + for( const auto evt : *this ) + { + if( selection != nullptr && !selection(evt) ) continue; + auto pos = projection(evt); + plot->Fill( pos, evt.weight() * ( weightFunction == nullptr ? 1 : weightFunction(evt) / evt.genPdf() ) ); + } + if( selection != nullptr ) INFO("Filter efficiency = " << plot->GetEntries() << " / " << size() ); + return plot; +} +TH2D* EventListSIMD::makeProjection( const Projection2D& projection, const ArgumentPack& args ) const +{ + auto selection = args.getArg().val; + auto weightFunction = args.getArg().val; + std::string prefix = args.getArg().val; + auto plot = projection.plot(prefix); + for ( const auto evt : *this ){ + if ( selection != nullptr && !selection(evt) ) continue; + auto pos = projection(evt); + plot->Fill( pos.first, pos.second, evt.weight() * ( weightFunction == nullptr ? 1 : weightFunction(evt) / evt.genPdf() ) ); + } + return plot; +} + +size_t EventListSIMD::getCacheIndex( const CompiledExpressionBase& PDF ) const +{ + auto pdfIndex = m_pdfIndex.find( FNV1a_hash( PDF.name() ) ); + if ( pdfIndex != m_pdfIndex.end() ) + return pdfIndex->second; + else + ERROR( "FATAL: PDF Index for " << PDF.name() << " not found" ); + return 999; +} + +size_t EventListSIMD::getCacheIndex( const CompiledExpressionBase& PDF, bool& isRegistered ) const +{ + auto pdfIndex = m_pdfIndex.find( FNV1a_hash( PDF.name() ) ); + if ( pdfIndex != m_pdfIndex.end() ) { + isRegistered = true; + return pdfIndex->second; + } + isRegistered = false; + return 999; +} + +void EventListSIMD::resetCache() +{ + m_pdfIndex.clear(); + m_cache.clear(); +} + +void EventListSIMD::clear() +{ + m_data.clear(); + m_cache.clear(); +} + +void EventListSIMD::reserveCache(const unsigned& newSize) +{ + m_cache.reserve( newSize * nBlocks() ); +} + +void EventListSIMD::resizeCache(const unsigned& newSize ) +{ + WARNING("Will only reserve, because i don't want to keep track anymore ... "); + reserveCache( newSize ); +} + +const Event EventListSIMD::operator[]( const size_t& pos ) const +{ + unsigned nEvents = size(); + unsigned p = pos / float_v::size; + unsigned q = pos % float_v::size; + Event tempEvent( m_eventSize ); + for( unsigned i = 0 ; i != m_eventSize; ++i ) + tempEvent[i] = m_data[p * m_eventSize + i ].at(q); + tempEvent.setWeight( m_weights[p].at(q) ); + tempEvent.setGenPdf( m_genPDF[p].at(q) ); + tempEvent.setIndex( pos ); + return tempEvent; +} + +std::array EventListSIMD::scatter( unsigned pos ) const +{ + unsigned p = pos / float_v::size; + std::array rt; + auto vw = m_weights[p].to_array(); + auto vg = m_genPDF[p].to_array(); + for( unsigned evt = 0 ; evt != float_v::size; ++evt ){ + rt[evt] = Event( m_eventSize ); + rt[evt].setWeight(vw[evt]); + rt[evt].setGenPdf(vg[evt]); + rt[evt].setIndex(evt + pos); + } + for( unsigned field = 0 ; field != m_eventSize; ++field){ + auto v = m_data[p * m_eventSize +field].to_array(); + for( unsigned evt = 0; evt != float_v::size; ++evt ) rt[evt][field] = v[evt]; + } + return rt; +} + +void EventListSIMD::gather( const std::array& data, unsigned pos ) +{ + for( unsigned field = 0 ; field != m_eventSize; ++field ) + m_data[pos*m_eventSize +field] = utils::gather(data, [field](auto& event){ return event[field]; } ); + m_weights[pos] = utils::gather(data, [](auto& event){ return event.weight() ; } ); + m_genPDF[pos] = utils::gather(data, [](auto& event){ return event.genPdf(); } ); +} + +#endif diff --git a/src/Expression.cpp b/src/Expression.cpp index aaf947bf391..88551e23f02 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -17,6 +17,8 @@ #include "AmpGen/Types.h" using namespace AmpGen; +using namespace AmpGen::fcn; +using namespace std::complex_literals; DEFINE_CAST(Constant ) DEFINE_CAST(Parameter ) @@ -53,10 +55,20 @@ std::string Constant::to_string(const ASTResolver* resolver) const { str.erase ( str.find_last_not_of('0') + 1, std::string::npos ); return str; }; - std::string complex_type_string = resolver != nullptr && resolver->enableCuda() ? "ampgen_cuda::complex_t" : typeof() ; - std::string literalSuffix = resolver != nullptr && resolver->enableCuda() ? "f" : ""; + std::string complex_type = typeof(); + std::string literalSuffix = ""; + if( resolver != nullptr && resolver->enableCuda() ) + { + complex_type = "ampgen_cuda::complex_t"; + literalSuffix = "f"; + } + if( resolver != nullptr && resolver->enableAVX() ) + { + complex_type = "AmpGen::AVX2::complex_t"; + literalSuffix = "f"; + } return std::imag(m_value) == 0 ? "(" + rounded_string(std::real(m_value)) +literalSuffix + ")" : - complex_type_string +"("+rounded_string(std::real(m_value))+literalSuffix+","+rounded_string(std::imag(m_value))+literalSuffix+")"; + complex_type +"("+rounded_string(std::real(m_value))+literalSuffix+","+rounded_string(std::imag(m_value))+literalSuffix+")"; } Expression simplify_constant_addition( const Constant& constant, const Expression& expression ) @@ -203,7 +215,9 @@ Ternary::Ternary( const Expression& cond, const Expression& v1, const Expression } std::string Ternary::to_string(const ASTResolver* resolver) const { - return "(" + m_cond.to_string(resolver) + "?" + m_v1.to_string(resolver) + ":" + m_v2.to_string(resolver) + ")"; + return resolver != nullptr && resolver->enableAVX() ? "AmpGen::AVX2::select(" + m_cond.to_string(resolver) + ", " + + m_v1.to_string(resolver) + ", " + m_v2.to_string(resolver) +")" + : "(" + m_cond.to_string(resolver) + "?" + m_v1.to_string(resolver) + ":" + m_v2.to_string(resolver) + ")"; } void Ternary::resolve( ASTResolver& resolver ) const @@ -295,7 +309,7 @@ Expression AmpGen::fcn::complex_sqrt( const Expression& expression ) { if( is(expression ) ) return sqrt( expression() ); auto st = make_cse(expression); - return Ternary( st > 0, Sqrt(st), Constant(0,1)*Sqrt(-st) ); + return Ternary( st > 0, Sqrt(st), 1i*Sqrt(-st) ); } Expression AmpGen::fcn::isqrt( const Expression& expression ) diff --git a/src/Generator.cpp b/src/Generator.cpp index 8383d4d5cac..30d30eb4f47 100644 --- a/src/Generator.cpp +++ b/src/Generator.cpp @@ -8,7 +8,7 @@ extern "C" void AmpGen::PyGenerate(const char* eventType, double* out, const uns EventType type( split( std::string(eventType),' ') ); INFO( type << " generating: " ); auto phsp = Generator(type, new TRandom3() ); - auto events = phsp.generate( size,0 ); + auto events = phsp.generate( size ); for( size_t i = 0 ; i < events.size(); ++i ){ for( size_t j = 0 ; j < events[i].size(); ++j) out[events[i].size() * i + j] = events[i][j]; diff --git a/src/IncoherentSum.cpp b/src/IncoherentSum.cpp index bce1e238814..2a75ae3ca1f 100644 --- a/src/IncoherentSum.cpp +++ b/src/IncoherentSum.cpp @@ -39,6 +39,7 @@ double IncoherentSum::norm( const Bilinears& norms ) const void IncoherentSum::prepare() { + /* if ( m_isConstant && m_prepareCalls != 0 ) return; transferParameters(); for ( auto& mE : m_matrixElements ) { @@ -47,11 +48,10 @@ void IncoherentSum::prepare() if ( m_prepareCalls != 0 && !amp.hasExternalsChanged() ) continue; if ( m_prepareCalls == 0 && m_events != nullptr ) mE.addressData = m_events->registerExpression( amp ); - if ( m_events != nullptr ) m_events->updateCache( amp, mE.addressData ); - if ( m_prepareCalls == 0 && m_integrator.isReady() ){ - m_integrator.prepareExpression( amp ); - } - INFO( mE.addressData << " " << m_events->at(0).getCache(mE.addressData) ); +// if ( m_events != nullptr ) m_events->updateCache( amp, mE.addressData ); + // if ( m_prepareCalls == 0 && m_integrator.isReady() ){ + // m_integrator.prepareExpression( amp ); + // } amp.resetExternals(); } if( m_prepareCalls == 0 ){ @@ -64,6 +64,7 @@ void IncoherentSum::prepare() m_prepareCalls++; m_norm = norm(); INFO( "norm = " << m_norm << " weight = " << m_weight ); + */ } std::vector IncoherentSum::fitFractions( const LinearErrorPropagator& linProp ) @@ -86,8 +87,8 @@ double IncoherentSum::prob( const Event& evt ) const double IncoherentSum::prob_unnormalised( const Event& evt ) const { double value( 0. ); - for ( auto& mE : m_matrixElements ) { - value += std::norm( mE.coefficient * evt.getCache( mE.addressData ) ); - } + //for ( auto& mE : m_matrixElements ) { + // value += std::norm( mE.coefficient * m_events->cache(evt.index(), mE.addressData ) ); + //} return value; } diff --git a/src/Integrator.cpp b/src/Integrator.cpp index e51f3d6639f..c1e45cf2d21 100644 --- a/src/Integrator.cpp +++ b/src/Integrator.cpp @@ -33,3 +33,80 @@ void Bilinears::resize( const size_t& r, const size_t& c) calculate[i] = true; } } + +void Integrator::integrateBlock() +{ + real_t re[N] = {0}; + real_t im[N] = {0}; + size_t addr_i[N] = {0}; + size_t addr_j[N] = {0}; + for( size_t roll = 0 ; roll < N; ++roll ) + { + addr_i[roll] = m_integrals[roll].i; + addr_j[roll] = m_integrals[roll].j; + } + for ( size_t roll = 0; roll < N; ++roll ) { + complex_t* b1 = m_cache.data() + m_integrals[roll].i * m_events->size(); + complex_t* b2 = m_cache.data() + m_integrals[roll].j * m_events->size(); + #pragma omp parallel for reduction(+: re, im) + for ( size_t i = 0; i < m_events->size(); ++i ) { + auto c = b1[i] * std::conj(b2[i]); + re[roll] += m_weight[i] * std::real(c); + im[roll] += m_weight[i] * std::imag(c); + } + } + for ( size_t j = 0; j < m_counter; ++j ) m_integrals[j].transfer( complex_t( re[j], im[j] ) / m_norm ); + m_counter = 0; +} + +Integrator::Integrator( const EventList* events ) : m_events( events ) +{ + if( m_events == nullptr ) return; + m_weight.resize( m_events->size() ); + for( size_t i = 0 ; i < m_events->size(); ++i ) + { + m_weight[i] = m_events->at(i).weight() / m_events->at(i).genPdf(); + m_norm += m_weight[i]; + } +} + +bool Integrator::isReady() const { return m_events != nullptr; } +const EventList* Integrator::events() const { return m_events; } +void Integrator::queueIntegral(const size_t& c1, + const size_t& c2, + const size_t& i, + const size_t& j, + Bilinears* out, + const bool& sim) +{ + if( !out->workToDo(i,j) ) return; + if( sim ) + addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ + out->set(i,j,val); + if( i != j ) out->set(j,i, std::conj(val) ); } ); + else + addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ out->set(i,j,val); } ); +} +void Integrator::addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ) +{ + m_integrals[m_counter++] = Integral(c1,c2,tFunc); + if ( m_counter == N ) integrateBlock(); +} +void Integrator::queueIntegral(const size_t& i, const size_t& j, complex_t* result) +{ + addIntegralKeyed(i, j, [result](arg& val){ *result = val ; } ); +} +void Integrator::flush() +{ + if ( m_counter == 0 ) return; + integrateBlock(); +} +void Integrator::setBuffer( complex_t* pos, const complex_t& value, const size_t& size ) +{ + *pos = value; +} + +void Integrator::setBuffer( complex_t* pos, const std::vector& value, const size_t& size) +{ + memcpy( pos, &(value[0]), size * sizeof(complex_t) ); +} diff --git a/src/Integrator2.cpp b/src/Integrator2.cpp deleted file mode 100644 index c36df07a789..00000000000 --- a/src/Integrator2.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "AmpGen/Integrator2.h" - -using namespace AmpGen; - -void Integrator2::integrateBlock() -{ - real_t re[N] = {0}; - real_t im[N] = {0}; - size_t addr_i[N] = {0}; - size_t addr_j[N] = {0}; - for( size_t roll = 0 ; roll < N; ++roll ) - { - addr_i[roll] = m_integrals[roll].i; - addr_j[roll] = m_integrals[roll].j; - } - for ( size_t roll = 0; roll < N; ++roll ) { - auto& b1 = m_buffer[m_integrals[roll].i]; - auto& b2 = m_buffer[m_integrals[roll].j]; - #pragma omp parallel for reduction(+: re, im) - for ( size_t i = 0; i < m_events->size(); ++i ) { - auto c = b1[i] * std::conj(b2[i]); - re[roll] += m_weight[i] * std::real(c); - im[roll] += m_weight[i] * std::imag(c); - } - } - for ( size_t j = 0; j < m_counter; ++j ) m_integrals[j].transfer( complex_t( re[j], im[j] ) / m_norm ); - m_counter = 0; -} - -Integrator2::Integrator2( const EventList* events ) : m_events( events ) -{ - if( m_events == nullptr ) return; - m_weight.resize( m_events->size() ); - for( size_t i = 0 ; i < m_events->size(); ++i ) - { - m_weight[i] = m_events->at(i).weight() / m_events->at(i).genPdf(); - m_norm += m_weight[i]; - } -} - -bool Integrator2::isReady() const { return m_events != nullptr; } -const EventList& Integrator2::events() const { return *m_events; } -void Integrator2::queueIntegral(const size_t& c1, - const size_t& c2, - const size_t& i, - const size_t& j, - Bilinears* out, - const bool& sim) -{ - if( !out->workToDo(i,j) ) return; - if( sim ) - addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ - out->set(i,j,val); - if( i != j ) out->set(j,i, std::conj(val) ); } ); - else - addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ out->set(i,j,val); } ); -} -void Integrator2::addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ) -{ - m_integrals[m_counter++] = Integral(c1,c2,tFunc); - if ( m_counter == N ) integrateBlock(); -} -void Integrator2::queueIntegral(const size_t& i, const size_t& j, complex_t* result) -{ - addIntegralKeyed(i, j, [result](arg& val){ *result = val ; } ); -} -void Integrator2::flush() -{ - if ( m_counter == 0 ) return; - integrateBlock(); -} -void Integrator2::setBuffer( complex_t* pos, const complex_t& value, const size_t& size ) -{ - *pos = value; -} - -void Integrator2::setBuffer( complex_t* pos, const std::vector& value, const size_t& size) -{ - memcpy( pos, &(value[0]), size * sizeof(complex_t) ); -} diff --git a/src/IntegratorSIMD.cpp b/src/IntegratorSIMD.cpp new file mode 100644 index 00000000000..375d84a3181 --- /dev/null +++ b/src/IntegratorSIMD.cpp @@ -0,0 +1,69 @@ +#include "AmpGen/IntegratorSIMD.h" +#include "AmpGen/simd/utils.h" + +using namespace AmpGen; +using namespace AmpGen::AVX2; + +void IntegratorSIMD::integrateBlock() +{ + #pragma omp parallel for + for ( size_t roll = 0; roll < N; ++roll ) { + float_v re( _mm256_set1_ps(0.f) ); + float_v im( _mm256_set1_ps(0.f) ); + auto b1 = m_cache.data() + m_integrals[roll].i * m_events->size(); + auto b2 = m_cache.data() + m_integrals[roll].j * m_events->size(); + for ( size_t i = 0; i < m_events->nBlocks(); ++i ) { + auto c = b1[i] * conj(b2[i]); + re = _mm256_fmadd_ps(re, m_weight[i], real(c) ); + im = _mm256_fmadd_ps(im, m_weight[i], imag(c) ); + } + m_integrals[roll].transfer( complex_t( utils::sum_elements(float_v(re)), + utils::sum_elements(float_v(im)) ) / m_norm ); + } + m_counter = 0; +} + +IntegratorSIMD::IntegratorSIMD( const EventListSIMD* events ) : m_events( events ) +{ + if( m_events == nullptr ) return; + m_weight.resize( m_events->nBlocks() ); + float_v norm_acc = 0.; + for( size_t i = 0 ; i < m_events->nBlocks(); ++i ) + { + m_weight[i] = m_events->weight(i) / m_events->genPDF(i); + norm_acc = norm_acc + m_weight[i]; + } + m_norm = utils::sum_elements(norm_acc); +} + +bool IntegratorSIMD::isReady() const { return m_events != nullptr; } + +void IntegratorSIMD::queueIntegral(const size_t& c1, + const size_t& c2, + const size_t& i, + const size_t& j, + Bilinears* out, + const bool& sim) +{ + if( !out->workToDo(i,j) ) return; + if( sim ) + addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ + out->set(i,j,val); + if( i != j ) out->set(j,i, std::conj(val) ); } ); + else + addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ out->set(i,j,val); } ); +} +void IntegratorSIMD::addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ) +{ + m_integrals[m_counter++] = Integral(c1,c2,tFunc); + if ( m_counter == N ) integrateBlock(); +} +void IntegratorSIMD::queueIntegral(const size_t& i, const size_t& j, complex_t* result) +{ + addIntegralKeyed(i, j, [result](arg& val){ *result = val ; } ); +} +void IntegratorSIMD::flush() +{ + if ( m_counter == 0 ) return; + integrateBlock(); +} diff --git a/src/Lineshapes.cpp b/src/Lineshapes.cpp index b101b615c37..7406c7d21db 100644 --- a/src/Lineshapes.cpp +++ b/src/Lineshapes.cpp @@ -23,8 +23,10 @@ Expression AmpGen::kFactor( const Expression& mass, const Expression& width, Deb return sqrt(k); } -Expression AmpGen::BlattWeisskopf_Norm( const Expression& z, const Expression& z0, unsigned int L ) +Expression AmpGen::BlattWeisskopf_Norm( const Expression& ze, const Expression& z0e, unsigned int L ) { + auto z = make_cse(ze); + auto z0 = make_cse(z0e); switch( L ) { case 0: return 1; case 1: return (1+z0) / (1+z); @@ -37,8 +39,9 @@ Expression AmpGen::BlattWeisskopf_Norm( const Expression& z, const Expression& z } } -Expression AmpGen::BlattWeisskopf( const Expression& z, unsigned int L ) +Expression AmpGen::BlattWeisskopf( const Expression& ze, unsigned int L ) { + auto z = make_cse(ze); switch( L ) { case 0: return 1; case 1: return 2 *fpow(z,1) / (1+z); @@ -75,27 +78,19 @@ Expression AmpGen::width( const Expression& s, const Expression& s1, const Expre const Expression& width, const Expression& radius, unsigned int L, DebugSymbols* dbexpressions ) { - auto q2v = make_cse( Q2(s,s1,s2) ); + auto q2v = make_cse( Q2(s,s1,s2) ); const Expression q2 = Ternary( q2v > 0, q2v, 0 ); - const Expression q20 = Abs( Q2( mass * mass, s1, s2 ) ); + const Expression q20 = abs( Q2( mass * mass, s1, s2 ) ); Expression BF = BlattWeisskopf_Norm( q2 * radius * radius, q20 * radius * radius, L ); - Expression qr = sqrt( q2 / q20 ) * fpow( q2/q20, L ); - - const Expression mreco = isqrt( s ); - const Expression mr = mass * mreco; + auto q2r = make_cse(q2 / q20); ADD_DEBUG(q2 , dbexpressions); ADD_DEBUG(q20 , dbexpressions); ADD_DEBUG(sqrt(q2/q20) , dbexpressions); ADD_DEBUG(BF , dbexpressions); - ADD_DEBUG(qr , dbexpressions); - ADD_DEBUG(mr , dbexpressions); - ADD_DEBUG(qr*mr , dbexpressions); - ADD_DEBUG(sqrt(q2)/mreco, dbexpressions); - ADD_DEBUG(sqrt(q20)/mass, dbexpressions); - ADD_DEBUG(width*BF*qr*mr, dbexpressions); - - return width * BF * qr * mr; + const auto rt = make_cse( width * BF * mass * sqrt( q2r / s ) * fpow( q2r, L ) ); + ADD_DEBUG(rt, dbexpressions); + return rt; } bool Lineshape::Factory::isLineshape( const std::string& lineshape ) @@ -142,8 +137,8 @@ Expression AmpGen::pol( const Expression& X, const std::vector& p ) Expression F = 0; Expression L = 1; for ( auto& ip : p ) { - F = F + ip * L; - L = L * X; + F += ip * L; + L *= X; } return F; } diff --git a/src/Lineshapes/kMatrix.cpp b/src/Lineshapes/kMatrix.cpp index 85b4937840e..5ba105bd98d 100644 --- a/src/Lineshapes/kMatrix.cpp +++ b/src/Lineshapes/kMatrix.cpp @@ -102,11 +102,11 @@ DEFINE_LINESHAPE( kMatrix ) std::vector fScatt = paramVector( "f_scatt", nChannels ); std::vector poleConfigs; - + bool addImaginaryMass = NamedParameter("kMatrix::fp", true ); for ( unsigned int pole = 1; pole <= nPoles; ++pole ) { std::string stub = "IS_p" + std::to_string( pole ) + "_"; Expression mass = Parameter( stub + "mass" ); - poleConfig p( mass * mass ); + poleConfig p( mass * mass + addImaginaryMass * (1i)*(1.e-6) ); /// add a tiny imaginary part to the mass to avoid floating point errors // for ( unsigned int ch = 0; ch < nChannels; ++ch ) p.add( Parameter( stub + channels[ch] ) ); poleConfigs.push_back( p ); } diff --git a/src/Minimiser.cpp b/src/Minimiser.cpp index 5589c1fb2d0..29cd3312e7b 100644 --- a/src/Minimiser.cpp +++ b/src/Minimiser.cpp @@ -59,7 +59,7 @@ void Minimiser::prepare() { std::string algorithm = NamedParameter( "Minimiser::Algorithm", "Hesse"); size_t maxCalls = NamedParameter( "Minimiser::MaxCalls" , 100000); - double tolerance = NamedParameter( "Minimiser::Tolerance" , 1); + double tolerance = NamedParameter( "Minimiser::Tolerance" , 2.0); m_printLevel = NamedParameter( "Minimiser::PrintLevel", 4); m_normalise = NamedParameter( "Minimiser::Normalise",false); if ( m_minimiser != nullptr ) delete m_minimiser; diff --git a/src/Particle.cpp b/src/Particle.cpp index e6b12032b3d..fdd239cc255 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -431,7 +431,14 @@ Expression Particle::getExpression( DebugSymbols* db, const unsigned int& index } ADD_DEBUG( total, db ); double nPermutations = doSymmetrisation ? orderings.size() : 1; - if ( sumAmplitudes ) return total / fcn::sqrt( nPermutations ); + if ( sumAmplitudes ) + { + if ( is(total) ){ + WARNING("Amplitude is just a constant: " << total << " may cause problems for compiler, making a little bit complex" ); + total += 1i * 0.00001; + } + return total / fcn::sqrt( nPermutations ); + } else { Expression sqrted = fcn::sqrt( total / nPermutations ); ADD_DEBUG( sqrted, db ); diff --git a/src/PhaseSpace.cpp b/src/PhaseSpace.cpp index 7eedb1b3f2c..c63be198602 100644 --- a/src/PhaseSpace.cpp +++ b/src/PhaseSpace.cpp @@ -35,12 +35,12 @@ double PhaseSpace::q( double m, double m1, double m2 ) const return 0.5 * sqrt( m*m - 2*m1*m1 - 2*m2*m2 + (m1*m1-m2*m2)*(m1*m1-m2*m2)/(m*m) ); } -Event PhaseSpace::makeEvent(const size_t& cacheSize) +Event PhaseSpace::makeEvent() { std::array rno; std::array pd; std::array invMas; - Event rt(4*m_nt + m_type.isTimeDependent(), cacheSize); + Event rt(4*m_nt + m_type.isTimeDependent()); rno[0] = 0; size_t n; diff --git a/src/Plots.cpp b/src/Plots.cpp deleted file mode 100644 index 800f12af2bc..00000000000 --- a/src/Plots.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#if __cplusplus >= 201402L -#include "AmpGen/ErrorPropagator.h" -#include "AmpGen/EventList.h" -#include "AmpGen/CoherentSum.h" -#include "AmpGen/IncoherentSum.h" -#include "AmpGen/Integrator.h" -#include "AmpGen/MinuitParameterSet.h" -#include "AmpGen/Projection.h" -#include "AmpGen/Utilities.h" -#include "AmpGen/EventList.h" -#include "AmpGen/Plots.h" -#include "AmpGen/DalitzIntegrator.h" - -#include "TFile.h" -#include "TH1D.h" -#include "TH2D.h" -#include -using namespace AmpGen; -void AmpGen::perAmplitudePlot( const EventList& evts, - const Projection& projection, - const CoherentSum& pdf ) -{ - struct PlotIJ { - unsigned int i; - unsigned int j; - TH1D* hist; - std::complex amp; - }; - - TDirectory* dir = (TDirectory*)gFile->Get( ("perAmp_"+projection.name()).c_str() ); - if( dir == nullptr ) - { - gFile->mkdir( ("perAmp_"+ projection.name() ).c_str() ); - dir = (TDirectory*)gFile->Get( ("perAmp_"+projection.name()).c_str() ); - } - dir->cd(); - - std::vector tmpPlots( pdf.size() * ( pdf.size() + 1 ) / 2 ); - - unsigned int s = 0; - for ( unsigned int i = 0; i < pdf.size(); ++i ) { - - for ( unsigned int j = i; j < pdf.size(); ++j ) { - auto pdf_i = pdf[i].amp; - auto pdf_j = pdf[j].amp; - unsigned int index_i = evts.getCacheIndex(pdf_i); - unsigned int index_j = evts.getCacheIndex(pdf_j); - const std::string name = pdf_i.name() + "_" + pdf_j.name(); - tmpPlots[s].hist = projection.plot(name); - tmpPlots[s].i = index_i; - tmpPlots[s].j = index_j; - tmpPlots[s].amp = pdf[i].coupling() * std::conj( pdf[j].coupling() ); - if ( index_i != index_j ) tmpPlots[s].amp = 2.0 * tmpPlots[s].amp; - s++; - } - } - for ( auto& evt : evts ) { - double f = projection( evt ); - for ( auto& h : tmpPlots ) { - std::complex pdfValue = evt.getCache( h.i ) * std::conj( evt.getCache( h.j ) ); - double weight = std::real( h.amp * pdfValue ) * evt.weight() / evt.genPdf(); - h.hist->Fill( f, weight ); - } - } - for ( auto& h : tmpPlots ) { - h.hist->Write(); - delete h.hist; - } - dir->Write(); - gFile->cd(); -} - -TGraph* AmpGen::boundary(const AmpGen::EventType& eventType, - const std::function& p1, - const std::function& p2 ) -{ - auto s0 = pow(eventType.motherMass(),2); - auto s1 = pow(eventType.mass(0),2); - auto s2 = pow(eventType.mass(1),2); - auto s3 = pow(eventType.mass(2),2); - - DalitzIntegrator di( s0, s1, s2, s3 ); - - TGraph* gboundary = new TGraph(); - - Event tmp(12); - - for( double x = 0 ; x <= 1; x+=0.001){ - di.setEvent( {x,0}, tmp.address() ); - gboundary->SetPoint( gboundary->GetN(), p1(tmp), p2(tmp) ); - } - for( double y = 0 ; y <= 1; y+=0.01){ - di.setEvent( {1,y}, tmp.address() ); - gboundary->SetPoint( gboundary->GetN(), p1(tmp), p2(tmp) ); - } - for( double x = 0 ; x <= 1; x+=0.001){ - di.setEvent( {1-x,1}, tmp.address() ); - gboundary->SetPoint( gboundary->GetN(), p1(tmp), p2(tmp) ); - } - for( double y = 0 ; y <= 1; y+=0.01){ - di.setEvent( {0,1-y}, tmp.address() ); - gboundary->SetPoint( gboundary->GetN(), p1(tmp), p2(tmp) ); - } - return gboundary; -} - -#endif diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index e63ab654231..34083588200 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -74,7 +74,7 @@ PolarisedSum::PolarisedSum(const EventType& type, m_matrixElements[i] = TransitionMatrix( p, coupling, - CompiledExpression( + CompiledExpression( TensorExpression(thisExpression), p.decayDescriptor(), this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,this->m_mps ) ); @@ -100,7 +100,7 @@ PolarisedSum::PolarisedSum(const EventType& type, m_matrixElements[i] = TransitionMatrix( tm.first, tm.second, - CompiledExpression( + CompiledExpression( TensorExpression(thisExpression), tm.first.decayDescriptor(), this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,this->m_mps ) ); @@ -192,11 +192,11 @@ void PolarisedSum::prepare() ProfileClock tEval; size_t size_of = size() / m_matrixElements.size(); if( m_events != nullptr ) m_events->reserveCache( size() ); - if( m_integrator.isReady() ) m_integrator.reserveCache( size() ); + if( m_integrator.isReady() ) m_integrator.allocate(m_matrixElements, size() ); for(auto& t : m_matrixElements){ if( m_nCalls != 0 && !t.amp.hasExternalsChanged() ) continue; m_events->updateCache(t.amp, t.addressData); - m_integrator.prepareExpression(t.amp, size_of); + m_integrator.prepareExpression(t.amp); t.amp.resetExternals(); t.workToDo = true; nChanges++; @@ -230,9 +230,9 @@ void PolarisedSum::prepare() void PolarisedSum::debug_norm() { double norm_slow = 0; - for( auto& evt : m_integrator.events() ) + for( auto& evt : *m_integrator.events() ) norm_slow += evt.weight() * getValNoCache(evt) / evt.genPdf(); - auto evt = m_integrator.events()[0]; + auto evt = (*m_integrator.events())[0]; INFO("Event[0]: " << prob_unnormalised(evt) << " " << getValNoCache(evt) ); INFO("Norm : " << std::setprecision(10) << "bilinears=" << m_norm @@ -252,7 +252,7 @@ void PolarisedSum::setEvents( EventList& events ) void PolarisedSum::setMC( EventList& events ) { m_nCalls = 0; - m_integrator = integrator(&events); + m_integrator = Integrator(&events); } @@ -267,7 +267,7 @@ void PolarisedSum::build_probunnormalised() { DebugSymbols db; auto prob = probExpression(transitionMatrix(), convertProxies(m_pVector,[](auto& p){ return Parameter(p->name());} ), m_debug ? &db : nullptr); - m_probExpression = CompiledExpression(prob, "prob_unnormalised", {}, db, m_mps); + m_probExpression = CompiledExpression(prob, "prob_unnormalised", {}, db, m_mps); CompilerWrapper().compile(m_probExpression); m_probExpression.prepare(); } @@ -290,7 +290,8 @@ Tensor PolarisedSum::transitionMatrix() real_t PolarisedSum::prob_unnormalised( const Event& evt ) const { - return m_probExpression( evt.getCachePtr(0) ); + return 0; + //return m_probExpression( &m_events->cache(evt.index(), 0) ); } double PolarisedSum::norm() const @@ -298,7 +299,7 @@ double PolarisedSum::norm() const return m_norm; } -complex_t PolarisedSum::norm(const size_t& i, const size_t& j, PolarisedSum::integrator* integ) +complex_t PolarisedSum::norm(const size_t& i, const size_t& j, Integrator* integ) { auto ai = m_integIndex[i]; auto aj = m_integIndex[j]; @@ -336,7 +337,7 @@ void PolarisedSum::debug(const Event& evt) for(const auto& me : m_matrixElements) { std::vector this_cache(0,tsize); - for(unsigned i = 0 ; i != tsize; ++i ) this_cache.emplace_back( evt.getCache(me.addressData+i) ); + for(unsigned i = 0 ; i != tsize; ++i ) this_cache.emplace_back( m_events->cache(evt.index(), me.addressData+i) ); INFO( me.decayDescriptor() << " " << vectorToString( this_cache, " ") ); } INFO("P(x) = " << getValNoCache(evt) ); @@ -344,15 +345,12 @@ void PolarisedSum::debug(const Event& evt) if( m_debug ) { transferParameters(); - Event copy(evt); - copy.resizeCache( size() ); - for(auto& me : m_matrixElements){ - auto values = me(copy); - copy.setCache( values , me.addressData ); - me.amp.debug( copy.address() ); + std::vector cache( tsize * m_matrixElements.size() ); + for( unsigned i = 0 ; i != m_matrixElements.size(); ++i ){ + std::memmove( cache.data() + tsize *i, m_matrixElements[i](evt).data(), tsize * sizeof(complex_t) ); + m_matrixElements[i].amp.debug( evt.address() ); } - m_probExpression.debug( copy.getCachePtr() ); - + m_probExpression.debug( cache.data() ); } } @@ -365,7 +363,7 @@ void PolarisedSum::generateSourceCode(const std::string& fname, const double& no Expression event = Parameter("x0",0,true); std::vector expressions(size); for( auto& p : m_matrixElements ){ - auto expr = CompiledExpression, const real_t*, const real_t*>( + auto expr = CompiledExpression(const real_t*, const real_t*)>( p.amp.expression(), p.decayDescriptor(), m_eventType.getEventFormat(), DebugSymbols() ,m_mps ) ; @@ -380,16 +378,16 @@ void PolarisedSum::generateSourceCode(const std::string& fname, const double& no T_matrix.st(); auto amp = probExpression(T_matrix, convertProxies(m_pVector, [](auto& proxy) -> Expression{ return double(proxy);} )); auto amp_extPol = probExpression(T_matrix, {Parameter("x2",0,true), Parameter("x3",0,true), Parameter("x4",0,true)}); - stream << CompiledExpression( amp / normalisation, "FCN",{},{}, m_mps ) << std::endl ; + const int&)>( amp / normalisation, "FCN",{},{}, m_mps ) << std::endl ; - stream << CompiledExpression( amp_extPol / normalisation, "FCN_extPol",{},{},m_mps ) << std::endl; + const double&)>( amp_extPol / normalisation, "FCN_extPol",{},{},m_mps ) << std::endl; stream.close(); } @@ -489,13 +487,12 @@ void PolarisedSum::transferParameters() real_t PolarisedSum::getValNoCache( const Event& evt ) { transferParameters(); - Event copy(evt); - copy.resizeCache( size() ); - for(auto& me : m_matrixElements){ - auto values = me(copy); - copy.setCache( values , me.addressData ); + auto tsize = m_dim.first * m_dim.second; + std::vector cache( tsize * m_matrixElements.size() ); + for( unsigned i = 0 ; i != m_matrixElements.size(); ++i ){ + std::memmove( cache.data() + tsize *i, m_matrixElements[i](evt).data(), tsize * sizeof(complex_t) ); } - return m_probExpression( copy.getCachePtr() ); + return m_probExpression( cache.data() ); } void PolarisedSum::setWeight( MinuitProxy param ){ m_weight = param; } @@ -503,7 +500,7 @@ double PolarisedSum::getWeight() const { return m_weight ; } std::function PolarisedSum::evaluator(const EventList* events) const { - if( events != nullptr && events != &this->m_integrator.events() ) + if( events != nullptr && events != m_integrator.events() ) ERROR("Evaluator only working on the integration sample, fix me!"); std::vector address_mapping( size() ); @@ -511,22 +508,22 @@ std::function PolarisedSum::evaluator(const EventList* eve for( unsigned i = 0; i != size() / m_matrixElements.size(); ++i ) address_mapping[me.addressData+i] = m_integrator.getCacheIndex( me.amp ) + i; } - std::vector values( m_integrator.events().size() ); + std::vector values( m_integrator.events()->size() ); std::vector buffer(address_mapping.size()); #ifdef _OPENMP #pragma omp parallel for firstprivate(buffer) #endif - for( unsigned int i = 0 ; i != m_integrator.events().size(); ++i ) + for( unsigned int i = 0 ; i != m_integrator.events()->size(); ++i ) { for( unsigned j = 0 ; j != address_mapping.size(); ++j ) buffer[j] = this->m_integrator.get(address_mapping[j], i); values[i] = m_weight * m_probExpression(&buffer[0]) / m_norm; } - return arrayToFunctor(values, events); + return arrayToFunctor(values); } KeyedView PolarisedSum::componentEvaluator(const EventList* events) const { - if( events != nullptr && events != &this->m_integrator.events() ) + if( events != nullptr && events != m_integrator.events() ) ERROR("Evaluator only working on the integration sample, fix me!"); KeyedView rt(*events, m_matrixElements.size() ); std::vector address_mapping(m_matrixElements.size()); @@ -540,7 +537,7 @@ KeyedView PolarisedSum::componentEvaluator(const EventList* e #ifdef _OPENMP #pragma omp parallel for #endif - for( unsigned evt = 0 ; evt != m_integrator.events().size(); ++evt ) + for( unsigned evt = 0 ; evt != m_integrator.events()->size(); ++evt ) { complex_t total = 0; for( unsigned j = 0 ; j != m_matrixElements.size(); ++j ){ diff --git a/src/Projection.cpp b/src/Projection.cpp index 1a16dbbd1b6..aeeb6901ebc 100644 --- a/src/Projection.cpp +++ b/src/Projection.cpp @@ -2,6 +2,7 @@ #include "AmpGen/Utilities.h" #include "AmpGen/Event.h" #include "AmpGen/EventList.h" +#include "AmpGen/EventListSIMD.h" #include #include "TAxis.h" @@ -70,17 +71,22 @@ std::pair Projection2D::operator()( const Event& evt ) const return {xAxis.m_func( evt ), yAxis.m_func( evt )}; } -TH1D* Projection::projInternal( const EventList& events, const ArgumentPack& args) const +template <> TH1D* Projection::projInternal( const EventList& events, const ArgumentPack& args) const { return events.makeProjection(*this, args); } -std::tuple, THStack*> Projection::projInternal(const EventList& events, const KeyedView& weightFunction, const ArgumentPack& args) const +template <> TH1D* Projection::projInternal( const EventListSIMD& events, const ArgumentPack& args) const +{ + return events.makeProjection(*this, args); +} + +template <> std::tuple, THStack*> Projection::projInternal(const EventList& events, const KeyedView& weightFunction, const ArgumentPack& args) const { -// INFO("Making projection: " << m_name << " classes = " << weightFunction.width() << " " << &(events[0]) ); std::vector hists; double norm_sum = args.getArg(1).val; std::string prefix = args.getArg().val; + bool autowrite = args.get() != nullptr; THStack* stack = args.getArg(new THStack()).val; if( prefix != "" ) prefix = prefix +"_"; for( unsigned int i = 0 ; i != weightFunction.width(); ++i ) @@ -97,7 +103,41 @@ std::tuple, THStack*> Projection::projInternal(const EventLis if( total == 0 ) ERROR("Norm = " << total ); else for( auto& h : hists ) h->Scale( norm_sum / total ); stack->SetName( (prefix + name() + "_stack").c_str()); - for( auto& h : hists ) stack->Add(h, "C HIST"); + for( auto& h : hists ){ + stack->Add(h, "C HIST"); + if( autowrite ) h->Write(); + } + if( autowrite ) stack->Write(); + return {hists, stack}; +} + +template <> std::tuple, THStack*> Projection::projInternal(const EventListSIMD& events, const KeyedView& weightFunction, const ArgumentPack& args) const +{ + std::vector hists; + double norm_sum = args.getArg(1).val; + std::string prefix = args.getArg().val; + bool autowrite = args.get() != nullptr; + THStack* stack = args.getArg(new THStack()).val; + if( prefix != "" ) prefix = prefix +"_"; + for( unsigned int i = 0 ; i != weightFunction.width(); ++i ) + hists.push_back( plot(prefix + weightFunction.key(i)==""?"C"+std::to_string(i):weightFunction.key(i)) ); + auto selection = args.getArg().val; + for( const auto& evt : events ){ + if( selection != nullptr && !selection(evt) ) continue; + auto pos = operator()(evt); + auto weights = weightFunction(evt); + for( unsigned j = 0 ; j != weightFunction.width(); ++j ) hists[j]->Fill( pos, evt.weight() * weights[j] / evt.genPdf() ); + } + std::sort( std::begin(hists), std::end(hists), [](auto& h1, auto& h2){ return h1->Integral() < h2->Integral() ; } ); + double total = std::accumulate( std::begin(hists), std::end(hists), 0.0, [](double& t, auto& h){ return t + h->Integral() ; } ); + if( total == 0 ) ERROR("Norm = " << total ); + else for( auto& h : hists ) h->Scale( norm_sum / total ); + stack->SetName( (prefix + name() + "_stack").c_str()); + for( auto& h : hists ){ + stack->Add(h, "C HIST"); + if( autowrite ) h->Write(); + } + if( autowrite ) stack->Write(); return {hists, stack}; } diff --git a/src/RecursivePhaseSpace.cpp b/src/RecursivePhaseSpace.cpp index ce812ab3e3a..c8f67908071 100644 --- a/src/RecursivePhaseSpace.cpp +++ b/src/RecursivePhaseSpace.cpp @@ -40,10 +40,10 @@ RecursivePhaseSpace::RecursivePhaseSpace(const Particle& decayChain, const Event setRandom( rndm ); } -AmpGen::Event RecursivePhaseSpace::makeEvent( const size_t& cacheSize ) +AmpGen::Event RecursivePhaseSpace::makeEvent() { - AmpGen::Event evt = m_phsp.makeEvent( cacheSize ); - AmpGen::Event rt( 4 * m_eventType.size(), cacheSize ); + AmpGen::Event evt = m_phsp.makeEvent(); + AmpGen::Event rt( 4 * m_eventType.size()); for (size_t i = 0; i < m_nodes.size(); ++i ) { auto& segment = m_nodes[i]; double px = evt[4*i + 0]; @@ -58,7 +58,7 @@ AmpGen::Event RecursivePhaseSpace::makeEvent( const size_t& cacheSize ) rt[4*segment.sink + 3] = pE; } } else { - auto evtTmp = segment.decayProds->makeEvent(cacheSize); + auto evtTmp = segment.decayProds->makeEvent(); double v = sqrt( px * px + py * py + pz * pz ) / pE; boost( evtTmp, std::tuple(px, py, pz), v ); for(size_t j = 0; j < rt.size(); ++j) rt[j] += evtTmp[j]; diff --git a/src/ThreeBodyCalculators.cpp b/src/ThreeBodyCalculators.cpp index fc7d1b9aa29..d6351163d76 100644 --- a/src/ThreeBodyCalculators.cpp +++ b/src/ThreeBodyCalculators.cpp @@ -136,18 +136,18 @@ double ThreeBodyCalculator::PartialWidth::getWidth( const double& s ) } Expression ThreeBodyCalculator::PartialWidth::spinAverageMatrixElement( - const std::vector>& elements, DebugSymbols* msym ) + const std::vector>& elements, DebugSymbols* msym ) { std::vector currents; - for ( auto& element : elements ) { - Particle particle(element.decayDescriptor(), type.finalStates() ); + for ( auto& [s, c] : elements ) { + Particle particle(s.decayDescriptor(), type.finalStates() ); auto perm = particle.identicalDaughterOrderings(); for ( auto& p : perm ) { particle.setOrdering(p); particle.setLineshape( "FormFactor" ); - Expression prop = make_cse( element.coupling.to_expression() ) * make_cse( particle.propagator( msym ) ); - if ( msym != nullptr ) msym->emplace_back( element.decayTree.name() + "_g", element.coupling.to_expression() ); - if ( msym != nullptr ) msym->emplace_back( element.decayTree.name() + "_p", particle.propagator() ); + Expression prop = make_cse( c.to_expression() ) * make_cse( particle.propagator( msym ) ); + if ( msym != nullptr ) msym->emplace_back( s.name() + "_g", c.to_expression() ); + if ( msym != nullptr ) msym->emplace_back( s.name() + "_p", particle.propagator() ); Tensor zt = particle.spinTensor(msym); zt.st() ; currents.push_back( zt * prop ); @@ -232,14 +232,17 @@ ThreeBodyCalculator::PartialWidth::PartialWidth( const EventType& evt, MinuitPar , type(evt) { DebugSymbols msym; - Expression matrixElementTotal = spinAverageMatrixElement( fcs.matrixElements(), &msym ); + std::vector> unpacked; + for( auto& p : fcs.matrixElements() ) unpacked.emplace_back( p.decayTree, p.coupling ); + + Expression matrixElementTotal = spinAverageMatrixElement(unpacked, &msym ); std::string name = ""; auto evtFormat = evt.getEventFormat(); - for ( auto& p : fcs.matrixElements() ) { - name += p.decayDescriptor(); - partialWidths.emplace_back( spinAverageMatrixElement( {p}, &msym ), p.decayDescriptor(), evtFormat, DebugSymbols(), &mps ); + for ( auto& p : unpacked ) { + name += p.first.decayDescriptor(); + partialWidths.emplace_back( spinAverageMatrixElement( {p}, &msym ), p.first.decayDescriptor(), evtFormat, DebugSymbols(), &mps ); } - totalWidth = CompiledExpression< std::complex, const real_t*, const real_t* > ( matrixElementTotal, "width", evtFormat, {} , &mps ); + totalWidth = CompiledExpression< complex_t(const real_t*, const real_t*) > ( matrixElementTotal, "width", evtFormat, {} , &mps ); CompilerWrapper(true).compile( totalWidth, ""); } diff --git a/src/TreePhaseSpace.cpp b/src/TreePhaseSpace.cpp index b2b5de5e232..18ea846740a 100644 --- a/src/TreePhaseSpace.cpp +++ b/src/TreePhaseSpace.cpp @@ -47,11 +47,11 @@ TreePhaseSpace::TreePhaseSpace(const std::vector& decayChains, const E m_dice = std::discrete_distribution<>(m_weights.begin(), m_weights.end()); } -Event TreePhaseSpace::makeEvent( const unsigned& cacheSize ) +Event TreePhaseSpace::makeEvent() { unsigned j = m_dice(m_gen); m_top[j].generate(); - auto event = m_top[j].event(m_type.size(), cacheSize); + auto event = m_top[j].event(m_type.size()); event.setGenPdf(genPdf(event) / m_top[j].weight()); m_generatorRecord.push_back(j); return event; @@ -195,9 +195,9 @@ void TreePhaseSpace::Vertex::place(Event& event) if( right != nullptr ) right->place(event); } -Event TreePhaseSpace::Vertex::event(const unsigned& eventSize, const unsigned& cacheSize) +Event TreePhaseSpace::Vertex::event(const unsigned& eventSize) { - Event output(4 * eventSize, cacheSize); + Event output(4 * eventSize); mom.SetXYZT(0,0,0,sqrt(s)); generateFullEvent(); place(output); diff --git a/src/UnaryExpression.cpp b/src/UnaryExpression.cpp index a00563c6833..0fb9b4c4994 100644 --- a/src/UnaryExpression.cpp +++ b/src/UnaryExpression.cpp @@ -17,7 +17,7 @@ T rsqrt( const T& arg ){ return 1. / sqrt(arg) ; } DEFINE_UNARY_OPERATOR( Log , log ) DEFINE_UNARY_OPERATOR( Sqrt, sqrt ) DEFINE_UNARY_OPERATOR( Exp , exp ) -DEFINE_UNARY_OPERATOR( Abs , std::abs ) +DEFINE_UNARY_OPERATOR_NO_RESOLVER( Abs , std::fabs ) DEFINE_UNARY_OPERATOR( Sin , sin ) DEFINE_UNARY_OPERATOR( Cos , cos ) DEFINE_UNARY_OPERATOR( Tan , tan ) @@ -28,17 +28,7 @@ DEFINE_UNARY_OPERATOR( Norm, std::norm ) DEFINE_UNARY_OPERATOR( Conj, std::conj ) DEFINE_UNARY_OPERATOR( Real, std::real ) DEFINE_UNARY_OPERATOR( Imag, std::imag ) -//DEFINE_UNARY_OPERATOR( LGamma, std::lgamma ); - //DEFINE_UNARY_OPERATOR( ISqrt, rsqrt ) - -ISqrt::ISqrt( const Expression& expression) : IUnaryExpression(expression) {} -ISqrt::operator Expression() const { return Expression( std::make_shared(*this) ) ; } -complex_t ISqrt::operator()() const { return 1./sqrt( m_expression() ); } -std::string ISqrt::to_string(const ASTResolver* resolver) const { - return resolver != nullptr && resolver->enableCuda() ? - "rsqrt("+m_expression.to_string(resolver)+")" : - "1./sqrt("+m_expression.to_string(resolver)+")" ; -} +DEFINE_UNARY_OPERATOR_NO_RESOLVER( ISqrt, rsqrt ) LGamma::LGamma( const Expression& expression) : IUnaryExpression(expression) {} LGamma::operator Expression() const { return Expression( std::make_shared(*this) ) ; } @@ -47,6 +37,19 @@ std::string LGamma::to_string(const ASTResolver* resolver) const { return "std::lgamma(" + m_expression.to_string(resolver) + ")"; } +std::string ISqrt::to_string(const ASTResolver* resolver) const { + return resolver != nullptr && resolver->enableCuda() ? + "rsqrt("+m_expression.to_string(resolver)+")" : + "1./sqrt("+m_expression.to_string(resolver)+")" ; +} + +std::string Abs::to_string( const ASTResolver* resolver ) const +{ + return resolver != nullptr && resolver->enableAVX() ? + "AmpGen::AVX2::abs(" + m_expression.to_string(resolver) +")" : + "std::fabs("+m_expression.to_string(resolver) +")"; +} + Expression Log::d() const { return 1. / arg(); } Expression Sqrt::d() const { return 1. / ( 2 * fcn::sqrt( arg() ) ); } Expression Exp::d() const { return fcn::exp(arg()) ; } diff --git a/test/test_phaseSpace.cpp b/test/test_phaseSpace.cpp index 4dc139124af..6bea1fd1380 100644 --- a/test/test_phaseSpace.cpp +++ b/test/test_phaseSpace.cpp @@ -27,7 +27,7 @@ BOOST_AUTO_TEST_CASE( phaseSpace_threeBody ) std::vector test_event = {-0.235918, -0.242689, 0.278177, 1.19862,-0.300608, -0.0584944, -0.0117436, 0.584418, 0.536526, 0.301183, -0.266434, 0.684864} ; - auto new_event = phsp.makeEvent(0); + auto new_event = phsp.makeEvent(); // auto new_event = phsp.generate(); for( int i = 0 ; i < 12 ; ++i ) From 7d2285853de0f9e233bfe9a041f53f31a53fb319 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 9 Apr 2020 17:35:09 +0200 Subject: [PATCH 164/250] add simd headers --- AmpGen/simd/avx2_types.h | 122 +++++++ AmpGen/simd/avx_mathfun.h | 727 ++++++++++++++++++++++++++++++++++++++ AmpGen/simd/iterator.h | 43 +++ AmpGen/simd/utils.h | 42 +++ 4 files changed, 934 insertions(+) create mode 100644 AmpGen/simd/avx2_types.h create mode 100644 AmpGen/simd/avx_mathfun.h create mode 100644 AmpGen/simd/iterator.h create mode 100644 AmpGen/simd/utils.h diff --git a/AmpGen/simd/avx2_types.h b/AmpGen/simd/avx2_types.h new file mode 100644 index 00000000000..a9ec3e082ee --- /dev/null +++ b/AmpGen/simd/avx2_types.h @@ -0,0 +1,122 @@ +#ifndef AMPGEN_AVX_TYPES +#define AMPGEN_AVX_TYPES 1 + +#include +#include +#include +#include +#include "AmpGen/simd/avx_mathfun.h" +#include + +namespace AmpGen { + namespace AVX2 { + struct float_t { + __m256 data; + static constexpr unsigned size = 8 ; + typedef float scalar_type; + float_t() = default; + float_t(__m256 data ) : data(data) {} + float_t(const float& f ) : data( _mm256_set1_ps(f) ) {} + float_t(const double& f ) : data( _mm256_set1_ps( float(f) )) {} + float_t(const float* f ) : data( _mm256_loadu_ps( f ) ) {} + void store( float* ptr ) const { _mm256_storeu_ps( ptr, data ); } + std::array to_array() const { std::array b; store( &b[0] ); return b; } + float at(const unsigned i) const { return to_array()[i] ; } + operator __m256() const { return data ; } + }; + + struct complex_t { + float_t re; + float_t im; + typedef std::complex scalar_type; + static constexpr unsigned size = 8 ; + + float_t real() const { return re; } + float_t imag() const { return im; } + complex_t() = default; + complex_t( const float_t& re, const float_t& im) : re(re), im(im) {} + complex_t( const float& re, const float& im) : re(re), im(im) {} + complex_t( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} + complex_t( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} + const std::complex at(const unsigned i) const { return std::complex(re.to_array()[i], im.to_array()[i]) ; } + void store( float* sre, float* sim ){ re.store(sre); im.store(sim); } + void store( std::complex* r ){ + auto re_arr = re.to_array(); + auto im_arr = im.to_array(); + for( unsigned i = 0 ; i != float_t::size; ++i ) r[i] = std::complex( re_arr[i], im_arr[i] ); + } + }; + + inline std::ostream& operator<<( std::ostream& os, const float_t& obj ) { + auto buffer = obj.to_array(); + for( unsigned i = 0 ; i != float_t::size; ++i ) os << buffer[i] << " "; + return os; + } + inline float_t operator+( const float_t& lhs, const float_t& rhs ) { return _mm256_add_ps(lhs, rhs); } + inline float_t operator-( const float_t& lhs, const float_t& rhs ) { return _mm256_sub_ps(lhs, rhs); } + inline float_t operator*( const float_t& lhs, const float_t& rhs ) { return _mm256_mul_ps(lhs, rhs); } + inline float_t operator/( const float_t& lhs, const float_t& rhs ) { return _mm256_div_ps(lhs, rhs); } + inline float_t operator-( const float_t& x ) { return -1.f * x; } + inline float_t operator&( const float_t& lhs, const float_t& rhs ) { return _mm256_and_ps( lhs, rhs ); } + inline float_t operator|( const float_t& lhs, const float_t& rhs ) { return _mm256_or_ps( lhs, rhs ); } + inline float_t operator^( const float_t& lhs, const float_t& rhs ) { return _mm256_xor_ps( lhs, rhs ); } + inline float_t operator+=(float_t& lhs, const float_t& rhs ){ lhs = lhs + rhs; return lhs; } + inline float_t operator-=(float_t& lhs, const float_t& rhs ){ lhs = lhs - rhs; return lhs; } + inline float_t operator*=(float_t& lhs, const float_t& rhs ){ lhs = lhs * rhs; return lhs; } + inline float_t operator/=(float_t& lhs, const float_t& rhs ){ lhs = lhs / rhs; return lhs; } + inline float_t operator&&( const float_t& lhs, const float_t& rhs ) { return _mm256_and_ps( lhs, rhs ); } + inline float_t operator||( const float_t& lhs, const float_t& rhs ) { return _mm256_or_ps( lhs, rhs ); } + inline float_t operator!( const float_t& x ) { return x ^ _mm256_castsi256_ps( _mm256_set1_epi32( -1 ) ); } + inline float_t operator<( const float_t& lhs, const float_t& rhs ) { return _mm256_cmp_ps( lhs, rhs, _CMP_LT_OS ); } + inline float_t operator>( const float_t& lhs, const float_t& rhs ) { return _mm256_cmp_ps( lhs, rhs, _CMP_GT_OS ); } + inline float_t operator==( const float_t& lhs, const float_t& rhs ){ return _mm256_cmp_ps( lhs, rhs, _CMP_EQ_OS ); } + inline float_t sqrt( const float_t& v ) { return _mm256_sqrt_ps(v); } + inline float_t sin( const float_t& v ) { return sin256_ps(v) ; } + inline float_t cos( const float_t& v ) { return cos256_ps(v) ; } + inline float_t tan( const float_t& v ) { float_t s; float_t c; sincos256_ps(v, (__m256*)&s, (__m256*)&c) ; return s/c; } + inline float_t log( const float_t& v ) { return log256_ps(v) ; } + inline float_t exp( const float_t& v ) { return exp256_ps(v) ; } + inline float_t abs ( const float_t& v ) { return v & _mm256_castsi256_ps( _mm256_set1_epi32( 0x7FFFFFFF ) ); } + inline float_t select(const float_t& mask, const float_t& a, const float_t& b ) { return _mm256_blendv_ps( b, a, mask ); } + inline float_t select(const bool& mask , const float_t& a, const float_t& b ) { return mask ? a : b; } + inline float_t atan2( const float_t& y, const float_t& x ){ + std::array bx{x.to_array()}, by{y.to_array()}, rt; + for( unsigned i = 0 ; i != float_t::size ; ++i ) rt[i] = std::atan2( by[i] , bx[i] ); + return float_t (rt.data() ); + } + inline float_t real(const complex_t& arg ){ return arg.re ; } + inline float_t imag(const complex_t& arg ){ return arg.im ; } + inline complex_t conj(const complex_t& arg ){ return complex_t(arg.re, -arg.im) ; } + inline complex_t operator+( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re + rhs, lhs.im); } + inline complex_t operator-( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re - rhs, lhs.im); } + inline complex_t operator*( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re*rhs, lhs.im*rhs); } + inline complex_t operator/( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re/rhs, lhs.im/rhs); } + inline complex_t operator+( const float_t& lhs, const complex_t& rhs ) { return complex_t(lhs + rhs.re, rhs.im); } + inline complex_t operator-( const float_t& lhs, const complex_t& rhs ) { return complex_t(lhs - rhs.re, - rhs.im); } + inline complex_t operator*( const float_t& lhs, const complex_t& rhs ) { return complex_t(lhs*rhs.re, lhs*rhs.im); } + inline complex_t operator/( const float_t& lhs, const complex_t& rhs ) { return complex_t( lhs * rhs.re , -lhs *rhs.im) / (rhs.re * rhs.re + rhs.im * rhs.im ); } + inline complex_t operator+( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re + rhs.re, lhs.im + rhs.im); } + inline complex_t operator-( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re - rhs.re, lhs.im - rhs.im); } + inline complex_t operator*( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re*rhs.re - lhs.im*rhs.im, lhs.re*rhs.im + lhs.im*rhs.re); } + inline complex_t operator/( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re*rhs.re + lhs.im*rhs.im, -lhs.re*rhs.im + lhs.im*rhs.re) / (rhs.re * rhs.re + rhs.im * rhs.im ); } + inline complex_t operator-( const complex_t& x ) { return -1.f * x; } + inline float_t abs( const complex_t& v ) { return sqrt( v.re * v.re + v.im * v.im ) ; } + inline float_t norm( const complex_t& v ) { return ( v.re * v.re + v.im * v.im ) ; } + inline complex_t select(const float_t& mask, const complex_t& a, const complex_t& b ) { return complex_t( _mm256_blendv_ps( b.re, a.re, mask ), _mm256_blendv_ps( b.im, a.im, mask ) ); } + inline complex_t select(const float_t& mask, const float_t& a, const complex_t& b ) { return complex_t( _mm256_blendv_ps( b.re, a , mask ), _mm256_blendv_ps( b.im, float_t(0.f), mask ) ); } + inline complex_t select(const float_t& mask, const complex_t& a, const float_t& b ) { return complex_t( _mm256_blendv_ps( b, a.re, mask ), _mm256_blendv_ps( float_t(0.f), a.im, mask ) ); } + inline complex_t select(const bool& mask , const complex_t& a, const complex_t& b ) { return mask ? a : b; } + inline complex_t exp( const complex_t& v ){ + float_t s; float_t c; sincos256_ps(v.im, (__m256*)&s, (__m256*)&c) ; + return exp( v.re ) * complex_t(c, s); + } + inline std::ostream& operator<<( std::ostream& os, const complex_t& obj ) { return os << "( "<< obj.re << ") (" << obj.im << ")"; } + #pragma omp declare reduction(+: float_t: \ + omp_out = omp_out + omp_in) + #pragma omp declare reduction(+: complex_t: \ + omp_out = omp_out + omp_in) + + } +} + +#endif diff --git a/AmpGen/simd/avx_mathfun.h b/AmpGen/simd/avx_mathfun.h new file mode 100644 index 00000000000..918a7a35f42 --- /dev/null +++ b/AmpGen/simd/avx_mathfun.h @@ -0,0 +1,727 @@ +#ifndef AMPGEN_AVX_MATHFUN_H +#define AMPGEN_AVX_MATHFUN_H 1 + +/* + AVX implementation of sin, cos, sincos, exp and log + + Based on "sse_mathfun.h", by Julien Pommier + http://gruntthepeon.free.fr/ssemath/ + + Copyright (C) 2012 Giovanni Garberoglio + Interdisciplinary Laboratory for Computational Science (LISC) + Fondazione Bruno Kessler and University of Trento + via Sommarive, 18 + I-38123 Trento (Italy) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + (this is the zlib license) + + modified 8/4/2020: inline all functions, as they end up wrapped anyway +*/ + +#include + +/* yes I know, the top of this file is quite ugly */ +# define ALIGN32_BEG +# define ALIGN32_END __attribute__((aligned(32))) + +/* __m128 is ugly to write */ +typedef __m256 v8sf; // vector of 8 float (avx) +typedef __m256i v8si; // vector of 8 int (avx) +typedef __m128i v4si; // vector of 8 int (avx) + +#define _PI32AVX_CONST(Name, Val) \ + static const ALIGN32_BEG int _pi32avx_##Name[4] ALIGN32_END = { Val, Val, Val, Val } + +_PI32AVX_CONST(1, 1); +_PI32AVX_CONST(inv1, ~1); +_PI32AVX_CONST(2, 2); +_PI32AVX_CONST(4, 4); + + +/* declare some AVX constants -- why can't I figure a better way to do that? */ +#define _PS256_CONST(Name, Val) \ + static const ALIGN32_BEG float _ps256_##Name[8] ALIGN32_END = { Val, Val, Val, Val, Val, Val, Val, Val } +#define _PI32_CONST256(Name, Val) \ + static const ALIGN32_BEG int _pi32_256_##Name[8] ALIGN32_END = { Val, Val, Val, Val, Val, Val, Val, Val } +#define _PS256_CONST_TYPE(Name, Type, Val) \ + static const ALIGN32_BEG Type _ps256_##Name[8] ALIGN32_END = { Val, Val, Val, Val, Val, Val, Val, Val } + +_PS256_CONST(1 , 1.0f); +_PS256_CONST(0p5, 0.5f); +/* the smallest non denormalized float number */ +_PS256_CONST_TYPE(min_norm_pos, int, 0x00800000); +_PS256_CONST_TYPE(mant_mask, int, 0x7f800000); +_PS256_CONST_TYPE(inv_mant_mask, int, ~0x7f800000); + +_PS256_CONST_TYPE(sign_mask, int, (int)0x80000000); +_PS256_CONST_TYPE(inv_sign_mask, int, ~0x80000000); + +_PI32_CONST256(0, 0); +_PI32_CONST256(1, 1); +_PI32_CONST256(inv1, ~1); +_PI32_CONST256(2, 2); +_PI32_CONST256(4, 4); +_PI32_CONST256(0x7f, 0x7f); + +_PS256_CONST(cephes_SQRTHF, 0.707106781186547524); +_PS256_CONST(cephes_log_p0, 7.0376836292E-2); +_PS256_CONST(cephes_log_p1, - 1.1514610310E-1); +_PS256_CONST(cephes_log_p2, 1.1676998740E-1); +_PS256_CONST(cephes_log_p3, - 1.2420140846E-1); +_PS256_CONST(cephes_log_p4, + 1.4249322787E-1); +_PS256_CONST(cephes_log_p5, - 1.6668057665E-1); +_PS256_CONST(cephes_log_p6, + 2.0000714765E-1); +_PS256_CONST(cephes_log_p7, - 2.4999993993E-1); +_PS256_CONST(cephes_log_p8, + 3.3333331174E-1); +_PS256_CONST(cephes_log_q1, -2.12194440e-4); +_PS256_CONST(cephes_log_q2, 0.693359375); + +#ifndef __AVX2__ + +typedef union imm_xmm_union { + v8si imm; + v4si xmm[2]; +} imm_xmm_union; + +#define COPY_IMM_TO_XMM(imm_, xmm0_, xmm1_) { \ + imm_xmm_union u __attribute__((aligned(32))); \ + u.imm = imm_; \ + xmm0_ = u.xmm[0]; \ + xmm1_ = u.xmm[1]; \ +} + +#define COPY_XMM_TO_IMM(xmm0_, xmm1_, imm_) { \ + imm_xmm_union u __attribute__((aligned(32))); \ + u.xmm[0]=xmm0_; u.xmm[1]=xmm1_; imm_ = u.imm; \ + } + + +#define AVX2_BITOP_USING_SSE2(fn) \ +static inline v8si avx2_mm256_##fn(v8si x, int a) \ +{ \ + /* use SSE2 instruction to perform the bitop AVX2 */ \ + v4si x1, x2; \ + v8si ret; \ + COPY_IMM_TO_XMM(x, x1, x2); \ + x1 = _mm_##fn(x1,a); \ + x2 = _mm_##fn(x2,a); \ + COPY_XMM_TO_IMM(x1, x2, ret); \ + return(ret); \ +} + +//#warning "Using SSE2 to perform AVX2 bitshift ops" +AVX2_BITOP_USING_SSE2(slli_epi32) +AVX2_BITOP_USING_SSE2(srli_epi32) + +#define AVX2_INTOP_USING_SSE2(fn) \ +static inline v8si avx2_mm256_##fn(v8si x, v8si y) \ +{ \ + /* use SSE2 instructions to perform the AVX2 integer operation */ \ + v4si x1, x2; \ + v4si y1, y2; \ + v8si ret; \ + COPY_IMM_TO_XMM(x, x1, x2); \ + COPY_IMM_TO_XMM(y, y1, y2); \ + x1 = _mm_##fn(x1,y1); \ + x2 = _mm_##fn(x2,y2); \ + COPY_XMM_TO_IMM(x1, x2, ret); \ + return(ret); \ +} + +//#warning "Using SSE2 to perform AVX2 integer ops" +AVX2_INTOP_USING_SSE2(and_si128) +AVX2_INTOP_USING_SSE2(andnot_si128) +AVX2_INTOP_USING_SSE2(cmpeq_epi32) +AVX2_INTOP_USING_SSE2(sub_epi32) +AVX2_INTOP_USING_SSE2(add_epi32) +#define avx2_mm256_and_si256 avx2_mm256_and_si128 +#define avx2_mm256_andnot_si256 avx2_mm256_andnot_si128 +#else +#define avx2_mm256_slli_epi32 _mm256_slli_epi32 +#define avx2_mm256_srli_epi32 _mm256_srli_epi32 +#define avx2_mm256_and_si256 _mm256_and_si256 +#define avx2_mm256_andnot_si256 _mm256_andnot_si256 +#define avx2_mm256_cmpeq_epi32 _mm256_cmpeq_epi32 +#define avx2_mm256_sub_epi32 _mm256_sub_epi32 +#define avx2_mm256_add_epi32 _mm256_add_epi32 +#endif /* __AVX2__ */ + + +/* natural logarithm computed for 8 simultaneous float + return NaN for x <= 0 +*/ +inline v8sf log256_ps(v8sf x) { + v8si imm0; + v8sf one = *(v8sf*)_ps256_1; + + //v8sf invalid_mask = _mm256_cmple_ps(x, _mm256_setzero_ps()); + v8sf invalid_mask = _mm256_cmp_ps(x, _mm256_setzero_ps(), _CMP_LE_OS); + + x = _mm256_max_ps(x, *(v8sf*)_ps256_min_norm_pos); /* cut off denormalized stuff */ + + // can be done with AVX2 + imm0 = avx2_mm256_srli_epi32(_mm256_castps_si256(x), 23); + + /* keep only the fractional part */ + x = _mm256_and_ps(x, *(v8sf*)_ps256_inv_mant_mask); + x = _mm256_or_ps(x, *(v8sf*)_ps256_0p5); + + // this is again another AVX2 instruction + imm0 = avx2_mm256_sub_epi32(imm0, *(v8si*)_pi32_256_0x7f); + v8sf e = _mm256_cvtepi32_ps(imm0); + + e = _mm256_add_ps(e, one); + + /* part2: + if( x < SQRTHF ) { + e -= 1; + x = x + x - 1.0; + } else { x = x - 1.0; } + */ + //v8sf mask = _mm256_cmplt_ps(x, *(v8sf*)_ps256_cephes_SQRTHF); + v8sf mask = _mm256_cmp_ps(x, *(v8sf*)_ps256_cephes_SQRTHF, _CMP_LT_OS); + v8sf tmp = _mm256_and_ps(x, mask); + x = _mm256_sub_ps(x, one); + e = _mm256_sub_ps(e, _mm256_and_ps(one, mask)); + x = _mm256_add_ps(x, tmp); + + v8sf z = _mm256_mul_ps(x,x); + + v8sf y = *(v8sf*)_ps256_cephes_log_p0; + y = _mm256_mul_ps(y, x); + y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p1); + y = _mm256_mul_ps(y, x); + y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p2); + y = _mm256_mul_ps(y, x); + y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p3); + y = _mm256_mul_ps(y, x); + y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p4); + y = _mm256_mul_ps(y, x); + y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p5); + y = _mm256_mul_ps(y, x); + y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p6); + y = _mm256_mul_ps(y, x); + y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p7); + y = _mm256_mul_ps(y, x); + y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p8); + y = _mm256_mul_ps(y, x); + + y = _mm256_mul_ps(y, z); + + tmp = _mm256_mul_ps(e, *(v8sf*)_ps256_cephes_log_q1); + y = _mm256_add_ps(y, tmp); + + + tmp = _mm256_mul_ps(z, *(v8sf*)_ps256_0p5); + y = _mm256_sub_ps(y, tmp); + + tmp = _mm256_mul_ps(e, *(v8sf*)_ps256_cephes_log_q2); + x = _mm256_add_ps(x, y); + x = _mm256_add_ps(x, tmp); + x = _mm256_or_ps(x, invalid_mask); // negative arg will be NAN + return x; +} + +_PS256_CONST(exp_hi, 88.3762626647949f); +_PS256_CONST(exp_lo, -88.3762626647949f); + +_PS256_CONST(cephes_LOG2EF, 1.44269504088896341); +_PS256_CONST(cephes_exp_C1, 0.693359375); +_PS256_CONST(cephes_exp_C2, -2.12194440e-4); + +_PS256_CONST(cephes_exp_p0, 1.9875691500E-4); +_PS256_CONST(cephes_exp_p1, 1.3981999507E-3); +_PS256_CONST(cephes_exp_p2, 8.3334519073E-3); +_PS256_CONST(cephes_exp_p3, 4.1665795894E-2); +_PS256_CONST(cephes_exp_p4, 1.6666665459E-1); +_PS256_CONST(cephes_exp_p5, 5.0000001201E-1); + +inline v8sf exp256_ps(v8sf x) { + v8sf tmp = _mm256_setzero_ps(), fx; + v8si imm0; + v8sf one = *(v8sf*)_ps256_1; + + x = _mm256_min_ps(x, *(v8sf*)_ps256_exp_hi); + x = _mm256_max_ps(x, *(v8sf*)_ps256_exp_lo); + + /* express exp(x) as exp(g + n*log(2)) */ + fx = _mm256_mul_ps(x, *(v8sf*)_ps256_cephes_LOG2EF); + fx = _mm256_add_ps(fx, *(v8sf*)_ps256_0p5); + + /* how to perform a floorf with SSE: just below */ + //imm0 = _mm256_cvttps_epi32(fx); + //tmp = _mm256_cvtepi32_ps(imm0); + + tmp = _mm256_floor_ps(fx); + + /* if greater, substract 1 */ + //v8sf mask = _mm256_cmpgt_ps(tmp, fx); + v8sf mask = _mm256_cmp_ps(tmp, fx, _CMP_GT_OS); + mask = _mm256_and_ps(mask, one); + fx = _mm256_sub_ps(tmp, mask); + + tmp = _mm256_mul_ps(fx, *(v8sf*)_ps256_cephes_exp_C1); + v8sf z = _mm256_mul_ps(fx, *(v8sf*)_ps256_cephes_exp_C2); + x = _mm256_sub_ps(x, tmp); + x = _mm256_sub_ps(x, z); + + z = _mm256_mul_ps(x,x); + + v8sf y = *(v8sf*)_ps256_cephes_exp_p0; + y = _mm256_mul_ps(y, x); + y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_exp_p1); + y = _mm256_mul_ps(y, x); + y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_exp_p2); + y = _mm256_mul_ps(y, x); + y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_exp_p3); + y = _mm256_mul_ps(y, x); + y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_exp_p4); + y = _mm256_mul_ps(y, x); + y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_exp_p5); + y = _mm256_mul_ps(y, z); + y = _mm256_add_ps(y, x); + y = _mm256_add_ps(y, one); + + /* build 2^n */ + imm0 = _mm256_cvttps_epi32(fx); + // another two AVX2 instructions + imm0 = avx2_mm256_add_epi32(imm0, *(v8si*)_pi32_256_0x7f); + imm0 = avx2_mm256_slli_epi32(imm0, 23); + v8sf pow2n = _mm256_castsi256_ps(imm0); + y = _mm256_mul_ps(y, pow2n); + return y; +} + +_PS256_CONST(minus_cephes_DP1, -0.78515625); +_PS256_CONST(minus_cephes_DP2, -2.4187564849853515625e-4); +_PS256_CONST(minus_cephes_DP3, -3.77489497744594108e-8); +_PS256_CONST(sincof_p0, -1.9515295891E-4); +_PS256_CONST(sincof_p1, 8.3321608736E-3); +_PS256_CONST(sincof_p2, -1.6666654611E-1); +_PS256_CONST(coscof_p0, 2.443315711809948E-005); +_PS256_CONST(coscof_p1, -1.388731625493765E-003); +_PS256_CONST(coscof_p2, 4.166664568298827E-002); +_PS256_CONST(cephes_FOPI, 1.27323954473516); // 4 / M_PI + + +/* evaluation of 8 sines at onces using AVX intrisics + + The code is the exact rewriting of the cephes sinf function. + Precision is excellent as long as x < 8192 (I did not bother to + take into account the special handling they have for greater values + -- it does not return garbage for arguments over 8192, though, but + the extra precision is missing). + + Note that it is such that sinf((float)M_PI) = 8.74e-8, which is the + surprising but correct result. + +*/ +inline v8sf sin256_ps(v8sf x) { // any x + v8sf xmm1, xmm2 = _mm256_setzero_ps(), xmm3, sign_bit, y; + v8si imm0, imm2; + +#ifndef __AVX2__ + v4si imm0_1, imm0_2; + v4si imm2_1, imm2_2; +#endif + + sign_bit = x; + /* take the absolute value */ + x = _mm256_and_ps(x, *(v8sf*)_ps256_inv_sign_mask); + /* extract the sign bit (upper one) */ + sign_bit = _mm256_and_ps(sign_bit, *(v8sf*)_ps256_sign_mask); + + /* scale by 4/Pi */ + y = _mm256_mul_ps(x, *(v8sf*)_ps256_cephes_FOPI); + + /* + Here we start a series of integer operations, which are in the + realm of AVX2. + If we don't have AVX, let's perform them using SSE2 directives + */ + +#ifdef __AVX2__ + /* store the integer part of y in mm0 */ + imm2 = _mm256_cvttps_epi32(y); + /* j=(j+1) & (~1) (see the cephes sources) */ + // another two AVX2 instruction + imm2 = avx2_mm256_add_epi32(imm2, *(v8si*)_pi32_256_1); + imm2 = avx2_mm256_and_si256(imm2, *(v8si*)_pi32_256_inv1); + y = _mm256_cvtepi32_ps(imm2); + + /* get the swap sign flag */ + imm0 = avx2_mm256_and_si256(imm2, *(v8si*)_pi32_256_4); + imm0 = avx2_mm256_slli_epi32(imm0, 29); + /* get the polynom selection mask + there is one polynom for 0 <= x <= Pi/4 + and another one for Pi/4 + +namespace AmpGen { + template class scatter_iterator + { + store_type* m_store; + std::array m_buffer; + size_t m_pos{0}; + public: + scatter_iterator( const size_t& pos, store_type* store ) : + m_store(store), + m_pos(pos) { + if( m_store != nullptr && pos < m_store->aligned_size()) m_buffer = m_store->scatter(pos / simd_size ); + } + stored_type* operator->() const { return &( m_buffer )[m_pos % simd_size]; } + stored_type operator*() const { return m_buffer [m_pos % simd_size]; } + stored_type& operator*() { return m_buffer [m_pos % simd_size]; } + scatter_iterator& operator++() + { + m_pos++; + if ( m_pos % simd_size == 0 ) + { + if constexpr(modifiable == true ) m_store->gather(m_buffer, (m_pos-1) / simd_size); + m_buffer = m_store->scatter( m_pos ); + } + return *this; + } + ~scatter_iterator() + { + if constexpr(modifiable == true) + { + if(m_store != nullptr && m_pos % simd_size != 0 ){ + m_store->gather(m_buffer, m_pos/simd_size); + } + } + } + bool operator==( const scatter_iterator& rhs ) const { return m_pos == rhs.m_pos ; } + bool operator!=( const scatter_iterator& rhs ) const { return m_pos != rhs.m_pos ; } + }; + template + auto make_scatter_iterator( const unsigned& pos, store_type* store) { + return scatter_iterator(pos, store) ; } +} diff --git a/AmpGen/simd/utils.h b/AmpGen/simd/utils.h new file mode 100644 index 00000000000..b8b5032a5e2 --- /dev/null +++ b/AmpGen/simd/utils.h @@ -0,0 +1,42 @@ +#include +#include "AmpGen/simd/avx2_types.h" + +namespace AmpGen { + namespace utils { + + template struct is_vector_type { static constexpr bool value = false; }; + template <> struct is_vector_type { static constexpr bool value = true ; }; + template <> struct is_vector_type { static constexpr bool value = true ; }; + + template simd_type gather( + const container_type& container, const functor_type& functor, unsigned offset=0, float df =0.) + { + std::array rv; + if( df == 0. ) + for( unsigned k = 0 ; k != simd_type::size; ++k ) rv[k] = offset + k < container.size() ? functor(container[offset+k]) : functor(container[container.size()-1]); + else + for( unsigned k = 0 ; k != simd_type::size; ++k ) rv[k] = offset + k < container.size() ? functor(container[offset+k]) : df; + return simd_type( rv.data() ); + } + + template size_t aligned_size( const size_t& unaligned_size ) { + return simd_type::size * unsigned ( 1 + (unaligned_size -1 ) / simd_type::size ); + } + template auto sum_elements( const simd_type& obj ) + { + if constexpr ( is_vector_type::value ) + { + auto arr = obj.to_array(); + auto rt = arr[0]; + for( unsigned i = 1 ; i != simd_type::size; ++i ) rt = rt + arr[i]; + return rt; + } + else return obj; + } + template auto get( vtype v ){ + if constexpr ( is_vector_type::value ) return v.at(p); + if constexpr ( ! is_vector_type::value ) return v; + } + + } +} From a46c0ff31bd8a48390a6d0ab643cc051ecc3f9c0 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 14 Apr 2020 18:41:56 +0200 Subject: [PATCH 165/250] Consolidate SIMD integration / caching code with scalar version, removed caching from eventlist into PDF --- AmpGen/AmplitudeRules.h | 72 ++++---- AmpGen/CoherentSum.h | 41 ++--- AmpGen/CompiledExpression.h | 21 ++- AmpGen/CompiledExpressionBase.h | 4 +- AmpGen/EventList.h | 63 +------ AmpGen/EventListSIMD.h | 84 +++------ AmpGen/EventType.h | 5 +- AmpGen/Generator.h | 6 +- AmpGen/Integrator.h | 122 ++++++------- AmpGen/IntegratorSIMD.h | 73 -------- AmpGen/MsgService.h | 113 ++++++------ AmpGen/PolarisedSum.h | 41 ++--- AmpGen/Store.h | 144 +++++++++++++++ AmpGen/SumPDF.h | 4 +- AmpGen/simd/avx2_types.h | 67 +++---- AmpGen/simd/avx2d_types.h | 152 ++++++++++++++++ AmpGen/simd/iterator.h | 2 + AmpGen/simd/utils.h | 84 +++++++-- Standalone.cmake | 15 +- apps/ConvertToSourceCode.cpp | 2 +- apps/Debugger.cpp | 14 +- apps/Generator.cpp | 2 +- examples/FitterWithPolarisation.cpp | 41 +++-- examples/QcGenerator.cpp | 2 +- src/CoherentSum.cpp | 189 +++++++++----------- src/CompiledExpressionBase.cpp | 7 +- src/CompilerWrapper.cpp | 3 +- src/ErrorPropagator.cpp | 2 +- src/EventList.cpp | 50 ++---- src/EventListSIMD.cpp | 89 +++------- src/Expression.cpp | 6 +- src/Integrator.cpp | 69 ++++---- src/IntegratorSIMD.cpp | 69 -------- src/Lineshapes/CoupledChannel.cpp | 4 +- src/Minimiser.cpp | 8 +- src/PolarisedSum.cpp | 264 +++++++++++++--------------- src/Projection.cpp | 13 +- src/Tensor.cpp | 6 +- src/UnaryExpression.cpp | 41 ++++- src/Utilities.cpp | 14 +- 40 files changed, 1024 insertions(+), 984 deletions(-) delete mode 100644 AmpGen/IntegratorSIMD.h create mode 100644 AmpGen/Store.h create mode 100644 AmpGen/simd/avx2d_types.h delete mode 100644 src/IntegratorSIMD.cpp diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index 2c57d2e5689..38823a0dc11 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -85,44 +85,38 @@ namespace AmpGen std::map> m_rules; }; - template struct TransitionMatrix + template struct TransitionMatrix : public CompiledExpression { - #if ENABLE_AVX2 - using float_v = AVX2::float_t; - #else - using float_v = real_t; - #endif + using amp_type = CompiledExpression; TransitionMatrix() = default; - TransitionMatrix(const Particle& dt, + TransitionMatrix(Particle dt, const TotalCoupling& coupling, - const CompiledExpression & amp) : + const amp_type& amp) : + amp_type(amp), decayTree(dt), - coupling(coupling), - amp(amp) {} + coupling(coupling) {} - TransitionMatrix(const Particle& dt, + TransitionMatrix(Particle dt, const TotalCoupling& coupling, const MinuitParameterSet& mps, const std::map& evtFormat, const bool& debugThis=false) : + amp_type(dt.getExpression(debugThis ? &db : nullptr ), dt.decayDescriptor(), evtFormat, db, &mps ), decayTree(dt), - coupling(coupling), - amp(decayTree.getExpression(debugThis ? &db : nullptr ), decayTree.decayDescriptor(), evtFormat, db, &mps ) {} + coupling(coupling) {} + #if ENABLE_AVX2 - const RT operator()(const Event& event) const { return amp(EventListSIMD::makeEvent(event).data()); } + const RT operator()(const Event& event) const { return amp_type::operator()(EventListSIMD::makeEvent(event).data()); } #else - const RT operator()(const Event& event) const { return amp(event.address()); } + const RT operator()(const Event& event) const { return amp_type::operator()(event.address()); } #endif const std::string decayDescriptor() const { return decayTree.decayDescriptor() ; } - std::string name() const { return amp.name(); } - unsigned returnTypeSize() const { return amp.returnTypeSize(); } Particle decayTree; TotalCoupling coupling; complex_t coefficient; DebugSymbols db; - CompiledExpression amp; - size_t addressData = {999}; + bool workToDo = {false}; }; template std::vector processIndex(const std::vector>& tm, const std::string& label) @@ -153,46 +147,46 @@ namespace AmpGen return rt; } - template <> struct TransitionMatrix + template <> struct TransitionMatrix : public CompiledExpression { + using amp_type = CompiledExpression; TransitionMatrix() = default; - TransitionMatrix(const Particle& dt, + TransitionMatrix(Particle dt, const TotalCoupling& coupling, - const CompiledExpression & amp) : + const amp_type& amp) : + amp_type(amp), decayTree(dt), - coupling(coupling), - amp(amp) {} + coupling(coupling) {} - TransitionMatrix(const Particle& dt, + TransitionMatrix(Particle dt, const TotalCoupling& coupling, const MinuitParameterSet& mps, const std::map& evtFormat, const bool& debugThis=false) : + amp_type(dt.getExpression(debugThis ? &db : nullptr ), dt.decayDescriptor(), evtFormat, db, &mps ), decayTree(dt), - coupling(coupling), - amp(decayTree.getExpression(debugThis ? &db : nullptr ), decayTree.decayDescriptor(), evtFormat, db, &mps ) { amp.use_rto();} + coupling(coupling) + { use_rto();} - const std::vector operator()(const Event& event) const { - std::vector rt(4); - amp(rt.data(), amp.externBuffer().data(), event.address() ); - return rt; - } - const std::vector operator()(const Event& event, const size_t& cacheOffset) const { - std::vector rt(4); - amp(rt.data(), amp.externBuffer().data(), event.address() + cacheOffset); + const std::vector operator()(const Event& event) const + { + std::vector rt(4); + #if ENABLE_AVX2 + amp_type::operator()(rt.data(), 1, externBuffer().data(), EventListSIMD::makeEvent(event).data()); + #else + amp_type::operator()(rt.data(), 1, externBuffer().data(), event.address()); + #endif return rt; } + const std::string decayDescriptor() const { return decayTree.decayDescriptor() ; } Particle decayTree; TotalCoupling coupling; complex_t coefficient; DebugSymbols db; - CompiledExpression amp; - size_t addressData = {999}; bool workToDo = {false}; - std::string name() const { return amp.name(); } - unsigned returnTypeSize() const { return amp.returnTypeSize(); } + unsigned size = {0}; }; } // namespace AmpGen diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index 41f8cdfa30d..89bd84cb3f6 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -16,12 +16,11 @@ #include "AmpGen/EventListSIMD.h" #include "AmpGen/EventType.h" #include "AmpGen/Integrator.h" -#include "AmpGen/IntegratorSIMD.h" #include "AmpGen/Types.h" #include "AmpGen/Event.h" #include "AmpGen/Projection.h" #include "AmpGen/MinuitParameter.h" - +#include "AmpGen/Store.h" namespace AmpGen { @@ -46,14 +45,8 @@ namespace AmpGen public: #if ENABLE_AVX2 using EventList_type = EventListSIMD; - using Integrator_type= IntegratorSIMD; - using complex_v = AVX2::complex_t; - using float_v = AVX2::float_t; #else using EventList_type = EventList; - using Integrator_type = Integrator; - using complex_v = complex_t; - using float_v = real_t; #endif CoherentSum(); CoherentSum( const EventType& type, const AmpGen::MinuitParameterSet& mps, const std::string& prefix = "" ); @@ -64,33 +57,30 @@ namespace AmpGen auto operator[]( const size_t& index ) { return m_matrixElements[index]; } const auto operator[]( const size_t& index ) const { return m_matrixElements[index]; } - size_t size() const { return m_matrixElements.size(); } - - real_t getWeight() const { return m_weight; } - real_t operator()( const Event& evt ) const { return m_weight*std::norm(getVal(evt))/m_norm; } - real_t prob( const Event& evt ) const { return m_weight*std::norm(getVal(evt))/m_norm; } - real_t prob_unnormalised( const Event& evt ) const { return std::norm(getVal(evt)); } - real_t norm( const Bilinears& norms ) const; + size_t size() const { return m_matrixElements.size(); } + real_t getWeight() const { return m_weight; } + real_t norm( const Bilinears& norms ) const; real_t norm() const; real_t getNorm( const Bilinears& normalisations ); complex_t norm( const size_t& x, const size_t& y ) const; complex_t getVal( const Event& evt ) const; - complex_t getValNoCache( const Event& evt ) const; - + complex_t getValNoCache( const Event& evt ) const; + void transferParameters(); void prepare(); void printVal( const Event& evt ); - void updateNorms( const std::vector& changedPdfIndices ); + void updateNorms(); void setWeight( MinuitProxy param ) { m_weight = param; } void makeTotalExpression(); void reset( bool resetEvents = false ); void setEvents( EventList_type& list ); #if ENABLE_AVX2 - void setEvents( EventList& list) { setEvents( *(new EventListSIMD(list)) ) ; } + void setEvents( EventList& list) { m_ownEvents = true; setEvents( *(new EventListSIMD(list)) ) ; } void setMC( EventList& list) { setMC( *(new EventListSIMD(list)) ) ; } - float_v operator()( const float_v*, const unsigned) const; #endif + float_v operator()(const float_v*, const unsigned) const; + real_t operator()(const Event& evt ) const { return m_weight*std::norm(getVal(evt))/m_norm; } void setMC( EventList_type& sim ); void debug( const Event& evt, const std::string& nameMustContain=""); @@ -106,20 +96,21 @@ namespace AmpGen KeyedView componentEvaluator(const EventList_type* = nullptr) const; protected: - std::vector> m_matrixElements; ///< Vector of (expanded) matrix elements + std::vector> m_matrixElements; ///< Vector of matrix elements Bilinears m_normalisations; ///< Normalisation integrals AmplitudeRules m_rules; ///< Ruleset for the selected transition. - Integrator_type m_integrator; ///< Integral dispatch tool (with default unroll = 10) - TransitionMatrix m_total; ///< Total Matrix Element + Integrator m_integrator; ///< Tool to calculate integrals EventList_type* m_events = {nullptr}; ///< Data events to evaluate PDF on - + Store m_cache; ///< Store of intermediate values for the PDF calculation + + bool m_ownEvents = {false}; ///< Flag as to whether events are owned by this PDF or not EventType m_evtType; ///< Final state for this amplitude size_t m_prepareCalls = {0}; ///< Number of times prepare has been called size_t m_lastPrint = {0}; ///< Last time verbose PDF info was printed size_t m_printFreq = {0}; ///< Frequency to print verbose PDF info MinuitProxy m_weight = {nullptr, 1}; ///< Weight (i.e. the normalised yield) - double m_norm = {0}; ///< Normalisation integral + double m_norm = {1}; ///< Normalisation integral bool m_isConstant = {false}; ///< Flag for a constant PDF bool m_dbThis = {false}; ///< Flag to generate amplitude level debugging bool m_verbosity = {false}; ///< Flag for verbose printing diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index 558f3588b56..be6c4eecfaf 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -9,7 +9,7 @@ #include "AmpGen/MsgService.h" #include "AmpGen/Utilities.h" #include "AmpGen/Types.h" - +#include "AmpGen/simd/utils.h" #include #include #include @@ -35,7 +35,7 @@ namespace AmpGen private: DynamicFCN m_fcn; - DynamicFCN m_batchFcn; + DynamicFCN m_batchFcn; DynamicFCN>(ARGS...)> m_fdb; std::vector m_externals = {}; bool m_hasExternalsChanged = {false}; @@ -64,13 +64,13 @@ namespace AmpGen bool use_rto() const override { return std::is_same::value; } - std::string args(bool includeTypes = false) const override + std::string args() const override { std::string signature; auto argTypes = typelist(); for( unsigned int i = 0 ; i < argTypes.size(); ++i ) { - signature += (includeTypes ? argTypes[i] : "") + " x"+std::to_string(i) ; + signature += " x"+std::to_string(i) ; if( i != argTypes.size() - 1 ) signature += ", "; } return signature; @@ -125,13 +125,16 @@ namespace AmpGen { stream << "#include \n"; stream << "extern \"C\" void " << progName() - << "_batch(" << returnTypename() << "* rt" - << ", const size_t& N, " + << "_batch("; + stream << " const size_t& N, " << " const size_t& eventSize, " - << " const size_t& cacheSize, " << args(true) << ") {\n"; + << " const size_t& cacheSize, "; + stream << typeof() << " * rt, "; + stream << CompiledExpressionBase::fcnSignature(typelist(), use_rto(), false) << ") {\n"; stream << "#pragma omp parallel for\n"; - stream << "for( unsigned int i = 0; i != N/8; ++i ){\n"; - stream << " rt[cacheSize*i] = " << progName() + "( x0, x1 + i * eventSize);"; + stream << "for( size_t i = 0; i != N/" << utils::size::value << "; ++i ){\n"; + if( use_rto() ) stream << progName() + "( r + cacheSize * i, s, x0, x1 + i * eventSize);"; + else stream << " rt[cacheSize*i] = " << progName() + "( x0, x1 + i * eventSize);"; stream << "}\n}"; } diff --git a/AmpGen/CompiledExpressionBase.h b/AmpGen/CompiledExpressionBase.h index d80f542b090..691f1f94685 100644 --- a/AmpGen/CompiledExpressionBase.h +++ b/AmpGen/CompiledExpressionBase.h @@ -53,11 +53,11 @@ namespace AmpGen virtual bool isReady() const = 0; virtual std::string returnTypename() const = 0; virtual std::string fcnSignature() const = 0; - virtual std::string args(bool=false) const = 0; + virtual std::string args() const = 0; virtual void print() const = 0; virtual ~CompiledExpressionBase(); virtual unsigned returnTypeSize() const = 0; - static std::string fcnSignature(const std::vector&, bool); + static std::string fcnSignature(const std::vector&, bool=false, bool=true); virtual bool use_rto() const = 0; Expression expression() const { return m_obj; } void enableBatch() { m_enableBatch = true ; } diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 260cd3affbd..d96f5326c91 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -31,10 +31,9 @@ namespace AmpGen { private: std::vector m_data = {}; - std::vector m_cache = {}; EventType m_eventType = {}; - std::map m_pdfIndex = {}; std::map m_extensions = {}; + public: typedef Event value_type; EventList() = default; @@ -55,8 +54,7 @@ namespace AmpGen { loadFromTree( tree, ArgumentPack(args...) ); } - - void resetCache(); + const EventList& store() const { return *this;} std::vector::reverse_iterator rbegin() { return m_data.rbegin(); } std::vector::reverse_iterator rend() { return m_data.rend(); } std::vector::iterator begin() { return m_data.begin(); } @@ -70,69 +68,22 @@ namespace AmpGen EventType eventType() const { return m_eventType; } const Event& at( const size_t& pos ) const { return m_data[pos]; } size_t size() const { return m_data.size(); } + size_t aligned_size() const { return m_data.size() ; } + size_t nBlocks() const { return m_data.size() ; } double integral() const; - + real_t weight( const size_t& pos) const { return m_data[pos].weight(); } + real_t genPDF( const size_t& pos) const { return m_data[pos].genPdf(); } void reserve( const size_t& size ) { m_data.reserve( size ); } void push_back( const Event& evt ) { m_data.push_back( evt ); } void setEventType( const EventType& type ) { m_eventType = type; } void add( const EventList& evts ); void loadFromTree( TTree* tree, const ArgumentPack& args ); void loadFromFile( const std::string& fname, const ArgumentPack& args ); - void printCacheInfo( const unsigned int& nEvt = 0 ); void clear(); void erase( const std::vector::iterator& begin, const std::vector::iterator& end ); TTree* tree( const std::string& name, const std::vector& extraBranches = {} ) const; - - size_t getCacheIndex( const CompiledExpressionBase& PDF, bool& status ) const; - size_t getCacheIndex( const CompiledExpressionBase& PDF ) const; - template size_t registerExpression(const T& expression, const size_t& size_of=0) - { - auto key = FNV1a_hash( expression.name() ); - auto pdfIndex = m_pdfIndex.find( key ); - if ( pdfIndex != m_pdfIndex.end() ) return pdfIndex->second; - else { - size_t expression_size = size_of == 0 ? expression.returnTypeSize() / sizeof(complex_t) : size_of; - m_pdfIndex[key] = m_cache.size() / m_data.size(); - m_cache.resize( m_cache.size() + m_data.size() * expression_size ); - return m_pdfIndex[key]; - } - } - complex_t cache( const unsigned& evtIndex, const unsigned& cacheElement ) - { - unsigned cacheSize = m_cache.size() / m_data.size(); - return m_cache[cacheSize * evtIndex + cacheElement]; - } - void setCache( const complex_t& v, const unsigned& p ) - { - m_cache[p] = v; - } - void setCache( const std::vector& v, const unsigned& p ) - { - std::memmove(m_cache.data() +p, v.data(), sizeof(complex_t) * v.size() ); - } - template void updateCache( const FCN& fcn, const size_t& index ) - { - unsigned cacheSize = m_cache.size() / m_data.size(); - if constexpr( std::is_same< typename FCN::return_type, void >::value ) - { - #ifdef _OPENMP - #pragma omp parallel for - #endif - for ( size_t evt = 0; evt < size(); ++evt ) - { - fcn( m_cache.data() + cacheSize*evt +index , fcn.externBuffer().data(), m_data[evt].address() ); - } - } - else { - #ifdef _OPENMP - #pragma omp parallel for - #endif - for ( size_t evt = 0; evt < size(); ++evt ) { setCache( fcn(m_data[evt].address() ), cacheSize*evt + index ) ; } - } - } - void reserveCache(const size_t& index); - void resizeCache(const size_t& newCacheSize ); + TH1D* makeProjection(const Projection& projection , const ArgumentPack& args = ArgumentPack()) const; TH2D* makeProjection(const Projection2D& projection, const ArgumentPack& args = ArgumentPack()) const; std::vector makeProjections( const std::vector& projections, const ArgumentPack& args ); diff --git a/AmpGen/EventListSIMD.h b/AmpGen/EventListSIMD.h index bad640db26c..61873b890c3 100644 --- a/AmpGen/EventListSIMD.h +++ b/AmpGen/EventListSIMD.h @@ -23,29 +23,20 @@ #include #endif -#if ENABLE_AVX2 - - #include "AmpGen/simd/avx2_types.h" - #include "AmpGen/simd/iterator.h" +#include "AmpGen/simd/iterator.h" +#include "AmpGen/simd/utils.h" +#include "AmpGen/Store.h" namespace AmpGen { - using float_v = AVX2::float_t; - using complex_v = AVX2::complex_t; - class CompiledExpressionBase; class EventListSIMD { private: - std::vector m_data = {}; - std::vector m_weights = {}; - std::vector m_genPDF = {}; - std::vector m_cache = {}; - EventType m_eventType = {}; - std::map m_pdfIndex = {}; - unsigned m_eventSize = {0}; - unsigned m_nEvents = {0}; - unsigned m_nBlocks = {0}; + Store m_data {}; + std::vector m_weights {}; + std::vector m_genPDF {}; + EventType m_eventType {}; public: typedef Event value_type; EventListSIMD() = default; @@ -66,63 +57,36 @@ namespace AmpGen { loadFromTree( tree, ArgumentPack(args...) ); } - const float_v* data() const { return m_data.data(); } - const AVX2::complex_t* cache() const { return m_cache.data() ; } EventListSIMD( const EventList& other ); - void resetCache(); - const AVX2::complex_t cache( const unsigned& evtIndex, const unsigned& cachePos ) - { - return m_cache[ (unsigned)(evtIndex/float_v::size) * cacheSize() + cachePos ]; - } + const float_v* data() const { return m_data.data(); } + operator Store () const { return m_data ; } + const auto& store() const { return m_data; } const Event at(const unsigned& p) const { return EventListSIMD::operator[](p) ; } - const float_v* block(const unsigned& p) { return m_data.data() + p * m_eventSize ; } + const float_v* block(const unsigned& p) { return m_data.data() + p * m_data.nFields(); } float_v weight(const unsigned& p) const { return m_weights[p]; } float_v genPDF(const unsigned& p) const { return m_genPDF[p]; } const Event operator[]( const size_t&) const; - std::array scatter(unsigned) const; - void gather(const std::array&, unsigned); - auto begin() const { return make_scatter_iterator(0,this); } - auto end() const { return make_scatter_iterator(m_nEvents, (const EventListSIMD*)(nullptr) ); } - auto begin() { return make_scatter_iterator(0, this); } - auto end() { return make_scatter_iterator(m_nEvents, (EventListSIMD*)(nullptr) ); } + std::array::value> scatter(unsigned) const; + void gather(const std::array::value>&, unsigned); + auto begin() const { return make_scatter_iterator::value>(0,this); } + auto end() const { return make_scatter_iterator::value>(size(), (const EventListSIMD*)(nullptr) ); } + auto begin() { return make_scatter_iterator::value, true>(0, this); } + auto end() { return make_scatter_iterator::value, true>(size(), (EventListSIMD*)(nullptr) ); } EventType eventType() const { return m_eventType; } - size_t aligned_size() const { return nBlocks() * float_v::size; } ///aligned number of events - size_t cacheSize() const { return m_cache.size() / m_nBlocks; } /// number of cached elements + size_t aligned_size() const { return m_data.aligned_size(); } double integral() const; - size_t eventSize() const { return m_eventSize; } - size_t size() const { return m_nEvents ; } - size_t nBlocks() const { return m_nBlocks; } - void reserve( const size_t& size ) { m_data.reserve( size * m_eventType.size() ); } - void setEventType( const EventType& type ) { m_eventType = type; m_eventSize = m_eventType.size(); } + size_t eventSize() const { return m_data.nFields(); } + size_t size() const { return m_data.size(); } + size_t nBlocks() const { return m_data.nBlocks(); } + void setEventType( const EventType& type ) { m_eventType = type; } void add( const EventListSIMD& evts ); void loadFromTree( TTree* tree, const ArgumentPack& args ); void loadFromFile( const std::string& fname, const ArgumentPack& args ); - void printCacheInfo( const unsigned int& nEvt = 0 ); void clear(); TTree* tree( const std::string& name, const std::vector& extraBranches = {} ) const; - size_t getCacheIndex( const CompiledExpressionBase& PDF, bool& status ) const; - size_t getCacheIndex( const CompiledExpressionBase& PDF ) const; - template unsigned registerExpression(const T& expression, const unsigned& size_of=0) - { - auto key = FNV1a_hash( expression.name() ); - auto pdfIndex = m_pdfIndex.find( key ); - if ( pdfIndex != m_pdfIndex.end() ) return pdfIndex->second; - else { - unsigned nEvents = aligned_size(); - unsigned expression_size = size_of == 0 ? expression.returnTypeSize() / sizeof(AmpGen::AVX2::complex_t) : size_of; - m_pdfIndex[key] = m_cache.size() / nBlocks(); - m_cache.resize(m_cache.size() + nBlocks() * expression_size); - return m_pdfIndex[key]; - } - } - template void updateCache( const FCN& fcn, const size_t& index ) - { - fcn.batch(m_cache.data() + index, aligned_size(), m_eventSize, cacheSize(), fcn.externBuffer().data(), m_data.data()); - } - void reserveCache(const unsigned& index); - void resizeCache( const unsigned& index); + TH1D* makeProjection(const Projection& projection , const ArgumentPack& args = ArgumentPack()) const; TH2D* makeProjection(const Projection2D& projection, const ArgumentPack& args = ArgumentPack()) const; std::vector makeProjections( const std::vector& projections, const ArgumentPack& args ); @@ -169,5 +133,3 @@ namespace AmpGen } // namespace AmpGen #endif - -#endif diff --git a/AmpGen/EventType.h b/AmpGen/EventType.h index d83dd26f815..93fa1467f03 100644 --- a/AmpGen/EventType.h +++ b/AmpGen/EventType.h @@ -15,6 +15,8 @@ namespace AmpGen Deals with final state configuration of events, specifically dealing with the ordering of particles in trees. */ + class EventType; + std::ostream& operator<<( std::ostream& os, const EventType& type ); class EventType { @@ -63,6 +65,8 @@ namespace AmpGen /// Calculates the number of spin indices associated with the initial and final state, i.e. the rank of the relevant transition matrix. std::pair dim() const; + + friend std::ostream& AmpGen::operator<<( std::ostream& os, const EventType& type ); private: std::string m_mother; ///< name of decaying particle @@ -76,7 +80,6 @@ namespace AmpGen std::pair m_dim; ///< Rank of the relevant transition matrix bool m_alt_part_names; ///< alternative naming in ouput tree (e.g. Xi- pi+ pi+ becomes Xim pip0 pip1 rather than _1_Xi# _2_pi~ _3_pi~) }; - std::ostream& operator<<( std::ostream& os, const EventType& type ); } // namespace AmpGen #endif diff --git a/AmpGen/Generator.h b/AmpGen/Generator.h index e55372e71b4..4a97856dadd 100644 --- a/AmpGen/Generator.h +++ b/AmpGen/Generator.h @@ -76,7 +76,7 @@ namespace AmpGen auto size0 = list.size(); auto tStartTotal = std::chrono::high_resolution_clock::now(); pdf.reset( true ); - ProgressBar pb(60, trimmedString(__PRETTY_FUNCTION__) ); + ProgressBar pb(60, detail::trimmedString(__PRETTY_FUNCTION__) ); ProfileClock t_phsp, t_eval, t_acceptReject; std::vector efficiencyReport(m_generatorBlock,false); @@ -92,7 +92,7 @@ namespace AmpGen if ( maxProb == 0 ) { double max = 0; for ( auto& evt : mc ) { - double value = pdf.prob_unnormalised(evt) / evt.genPdf(); + double value = pdf(evt) / evt.genPdf(); if ( value > max ) max = value; } maxProb = max * 1.5; @@ -104,7 +104,7 @@ namespace AmpGen #pragma omp parallel for #endif for ( size_t i=0; i < mc.size(); ++i ) - mc[i].setGenPdf(pdf.prob_unnormalised(mc[i]) / mc[i].genPdf()); + mc[i].setGenPdf(pdf(mc[i]) / mc[i].genPdf()); for( size_t i=0; i != mc.size(); ++i ) { diff --git a/AmpGen/Integrator.h b/AmpGen/Integrator.h index a83cce80da2..cc98c208031 100644 --- a/AmpGen/Integrator.h +++ b/AmpGen/Integrator.h @@ -3,9 +3,12 @@ #include "AmpGen/Types.h" #include "AmpGen/EventList.h" -#include "AmpGen/CompiledExpressionBase.h" #include #include +#include "AmpGen/simd/utils.h" +#include "AmpGen/Store.h" +#include "AmpGen/EventListSIMD.h" +#include "AmpGen/EventList.h" /* * Calculates Bilinears A_i A_j^* integrated over the phase-space. @@ -43,7 +46,7 @@ namespace AmpGen template struct Integral { - typedef std::function TransferFCN; + typedef std::function TransferFCN; size_t i = {0}; size_t j = {0}; TransferFCN transfer; @@ -51,80 +54,67 @@ namespace AmpGen Integral(const size_t& i, const size_t& j, TransferFCN t) : i(i), j(j), transfer(t) {} }; + class Integrator { - typedef const complex_t& arg; - typedef std::function TransferFCN; + typedef std::function TransferFCN; public: - explicit Integrator( const EventList* events = nullptr ); + Integrator() = default; - bool isReady() const; - const EventList* events() const; - void queueIntegral(const size_t& c1, - const size_t& c2, - const size_t& i, - const size_t& j, - Bilinears* out, - const bool& sim = true); - void addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ); - void queueIntegral(const size_t& i, const size_t& j, complex_t* result); - void flush(); - void setBuffer( complex_t* pos, const complex_t& value, const size_t& size ); - void setBuffer( complex_t* pos, const std::vector& value, const size_t& size); - complex_t get(const unsigned& i, const unsigned& evt) const { return m_cache[i * m_events->size() + evt ]; } - template unsigned getCacheIndex( const T& t ) const { return m_index.find( t.name() )->second.first; } - double norm() const { return m_norm; } - template void allocate( const std::vector& expressions, const size_t& size_of = 0) - { - if( m_events == nullptr ) return; - unsigned totalSize = 0; - for( unsigned i = 0; i != expressions.size(); ++i ){ - size_t vsize = size_of == 0 ? expressions[i].returnTypeSize() / sizeof(complex_t) : size_of; - m_index[ expressions[i].name() ] = std::make_pair(totalSize, vsize); - totalSize += vsize; - } - m_cache.resize( m_events->size() * totalSize ); + template Integrator( const EventList_type* events, const std::vector& expressions ={}, const size_t& size_of =0) : m_events(events) + { + if( events == nullptr ) { + WARNING("No events specified, returning"); + return; } - - template void prepareExpression(const T& expression) + m_cache = Store(events->size(), expressions, size_of ); + m_weight.resize( events->nBlocks() ); + float_v norm_acc = 0.; + for( size_t i = 0 ; i < events->nBlocks(); ++i ) { - if( m_events == nullptr ) return; - auto f = m_index.find( expression.name() ); - if( f == m_index.end() ) FATAL("Expression: " << expression.name() << " is not registed"); - auto [p0, s] = f->second; - INFO("Preparing: " << expression.name() << " index = " << p0 << " with: " << s << " values" ); - if constexpr( std::is_same< typename T::return_type, void >::value ) - { - #ifdef _OPENMP - #pragma omp parallel for - #endif - for ( size_t i = 0; i < m_events->size(); ++i ) - { - std::vector buf(s); - expression(&buf[0], expression.externBuffer().data(), m_events->at(i).address() ); - for( unsigned j = 0; j != s; ++j ) m_cache[ (p0+j) * m_events->size() + i] = buf[j]; - } - } - else { - #ifdef _OPENMP - #pragma omp parallel for - #endif - for ( size_t i = 0; i < m_events->size(); ++i ) - setBuffer( &(m_cache[p0 * m_events->size() +i] ), expression(m_events->at(i).address()),s ); - } + m_weight[i] = events->weight(i) / events->genPDF(i); + norm_acc = norm_acc + m_weight[i]; } + m_norm = utils::sum_elements(norm_acc); + } + + bool isReady() const; + void queueIntegral(const size_t& c1, + const size_t& c2, + const size_t& i, + const size_t& j, + Bilinears* out, + const bool& sim = true); + void addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ); + void queueIntegral(const size_t& i, const size_t& j, complex_t* result); + void flush(); + template return_type get( const unsigned& index, const unsigned& evt ) const ; + template unsigned getCacheIndex( const T& t ) const { return m_cache.find(t) ; } + double norm() const { return m_norm; } + + template void updateCache(const T& expression) + { + #if ENABLE_AVX2 + if( m_events != nullptr ) m_cache.update( static_cast(m_events)->store(), expression ); + #else + if( m_events != nullptr ) m_cache.update( static_cast(m_events)->store(), expression ); + #endif + } + template + const T* events() const { return static_cast(m_events) ; } + private: - static constexpr size_t N = {10}; ///unroll factor - size_t m_counter = {0}; /// - std::array, N> m_integrals; - const EventList* m_events = {nullptr}; - std::vector m_cache; - std::vector m_weight; - std::map> m_index; - double m_norm = {0}; - void integrateBlock(); + static constexpr size_t N = {8}; ///unroll factor + size_t m_counter = {0}; /// + std::array, N> m_integrals; + const void* m_events = {nullptr}; + std::vector m_weight; + Store m_cache; + double m_norm = {0}; + void integrateBlock(); }; + } // namespace AmpGen #endif diff --git a/AmpGen/IntegratorSIMD.h b/AmpGen/IntegratorSIMD.h deleted file mode 100644 index 2e166cd1294..00000000000 --- a/AmpGen/IntegratorSIMD.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef AMPGEN_INTEGRATORSIMD_H -#define AMPGEN_INTEGRATORSIMD_H 1 - -#if ENABLE_AVX2 - -#include "AmpGen/Integrator.h" -#include "AmpGen/simd/avx2_types.h" -#include "AmpGen/EventListSIMD.h" - -namespace AmpGen { - /// test /// - class IntegratorSIMD - { - typedef const complex_t& arg; - typedef std::function TransferFCN; - - public: - explicit IntegratorSIMD( const EventListSIMD* events = nullptr ); - - bool isReady() const; - void queueIntegral(const size_t& c1, - const size_t& c2, - const size_t& i, - const size_t& j, - Bilinears* out, - const bool& sim = true); - void addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ); - void queueIntegral(const size_t& i, const size_t& j, complex_t* result); - void flush(); - complex_t get(const unsigned& i, const unsigned& evt) const { return m_cache[i * m_events->size() + evt/float_v::size ].at( evt % float_v::size ); } - template unsigned getCacheIndex( const T& t ) const { return m_index.find( t.name() )->second.first; } - double norm() const { return m_norm; } - const EventListSIMD* events() const { return m_events; } - template void allocate( const std::vector& expressions, const size_t& size_of = 0) - { - if( m_events == nullptr ) return; - unsigned totalSize = 0; - for( unsigned i = 0; i != expressions.size(); ++i ){ - size_t vsize = size_of == 0 ? expressions[i].returnTypeSize() / sizeof(AVX2::complex_t) : size_of; - m_index[ expressions[i].name() ] = std::make_pair(totalSize, vsize); - totalSize += vsize; - } - m_cache.resize( m_events->size() * totalSize ); - } - - template void prepareExpression(const T& expression) - { - if( m_events == nullptr ) return; - auto f = m_index.find( expression.name() ); - if( f == m_index.end() ) FATAL("Expression: " << expression.name() << " is not registed"); - auto [p0, s] = f->second; - expression.batch(m_cache.data() + p0*m_events->aligned_size(), - m_events->aligned_size(), - m_events->eventSize(), - 1, - expression.externBuffer().data(), - m_events->data() ); - } - - private: - static constexpr size_t N = {10}; ///unroll factor - size_t m_counter = {0}; /// - std::array, N> m_integrals; - const EventListSIMD* m_events = {nullptr}; - std::vector m_cache; - std::vector m_weight; - std::map> m_index; - double m_norm = {0}; - void integrateBlock(); - }; -} -#endif -#endif diff --git a/AmpGen/MsgService.h b/AmpGen/MsgService.h index a8d8c873585..3067529e460 100644 --- a/AmpGen/MsgService.h +++ b/AmpGen/MsgService.h @@ -2,98 +2,93 @@ #define AMPGEN_MSGSERVICE_H /** @defgroup msgService Messaging and logging - MsgService Header - Defines coloured and organised output macro streams using __PRETTY_FUNCTION__ - INFO() - info level messages, always displayed - ERROR() - error level messages, always displayed - FATAL() - error message that throws the process, always displayed - WARNING() - warning level messages, can be switched with the WARNINGLEVEL flag - DEBUG() - debug level messages, can be switched with the DEBUGLEVEL flag - */ + MsgService Header + Defines coloured and organised output macro streams using __PRETTY_FUNCTION__ + INFO() - info level messages, always displayed + ERROR() - error level messages, always displayed + FATAL() - error message that throws the process, always displayed + WARNING() - warning level messages, can be switched with the WARNINGLEVEL flag + DEBUG() - debug level messages, can be switched with the DEBUGLEVEL flag + */ #include #include #include +#include #define WARNINGLEVEL 1 -//#define DEBUGLEVEL 0 -//#define TRACELEVEL 0 #define FCNNAMELENGTH 45 -inline std::string trimmedString( std::string thing, const unsigned int& length = FCNNAMELENGTH ) -{ - size_t pos2=0; - do { - pos2 = thing.find( "AmpGen::" ); - if ( pos2 != std::string::npos ) thing = thing.replace( pos2, 8, "" ); - } while( pos2 != std::string::npos ); - - pos2 = thing.find( "std::" ); - if ( pos2 != std::string::npos ) thing.replace( pos2, 5, "" ); - - pos2 = thing.find( "virtual " ); - if ( pos2 != std::string::npos ) thing = thing.replace( pos2, 8, "" ); - - size_t pos = thing.find( "(" ); - - if ( pos != std::string::npos ) { - return pos < length ? thing.substr( 0, pos ) : thing.substr( 0, length ); +namespace AmpGen { + namespace detail { + inline std::string trimmedString( std::string thing, const unsigned int& length = FCNNAMELENGTH ) + { + size_t pos2=0; + do { + pos2 = thing.find( "AmpGen::" ); + if ( pos2 != std::string::npos ) thing = thing.replace( pos2, 8, "" ); + } while( pos2 != std::string::npos ); + + pos2 = thing.find( "std::" ); + if ( pos2 != std::string::npos ) thing.replace( pos2, 5, "" ); + + pos2 = thing.find( "virtual " ); + if ( pos2 != std::string::npos ) thing = thing.replace( pos2, 8, "" ); + + size_t pos = thing.find( "(" ); + + if ( pos != std::string::npos ) { + return pos < length ? thing.substr( 0, pos ) : thing.substr( 0, length ); + } + return thing.size() < length ? thing : thing.substr( 0, length ) + "..."; + } + template struct debug_type : std::false_type {}; } - return thing.size() < length ? thing : thing.substr( 0, length ) + "..."; } +#define ENABLE_DEBUG(X) \ + namespace AmpGen { namespace detail { template <> struct debug_type : std::true_type {}; } } + /// @ingroup msgService macro DEBUG /// Used for printing verbose debugging messages, only if DEBUGLEVEL is defined. -#ifdef DEBUGLEVEL -#define DEBUG( X ) \ - std::cout << "\033[2;32m" << std::left << std::setw( FCNNAMELENGTH ) << trimmedString( __PRETTY_FUNCTION__ ) \ -<< " DEBUG " \ -<< "\033[0m" << X << std::endl -#else -#define DEBUG( X ) -#endif +#define DEBUG( X ) { \ + if constexpr( AmpGen::detail::debug_type::type>::value ) { \ + std::cout << "\033[2;32m" << std::left << std::setw( FCNNAMELENGTH ) << AmpGen::detail::trimmedString(__PRETTY_FUNCTION__) \ + << " DEBUG " \ + << "\033[0m" << X << " " << std::endl; } } /// @ingroup msgService macro INFO /// Used for printing information messages, and will always be printed. #define INFO( X ) \ - std::cout << "\033[2;34m" << std::left << std::setw( FCNNAMELENGTH ) << trimmedString( __PRETTY_FUNCTION__ ) \ -<< " INFO " \ -<< "\033[0m" << X << std::endl + std::cout << "\033[2;34m" << std::left << std::setw( FCNNAMELENGTH ) << detail::trimmedString( __PRETTY_FUNCTION__ ) \ + << " INFO " \ + << "\033[0m" << X << std::endl /// @ingroup msgService macro ERROR /// Used for printing errors messages, and will always be printed. #define ERROR( X ) \ - std::cout << "\033[1;31m" << std::left << std::setw( FCNNAMELENGTH ) << trimmedString( __PRETTY_FUNCTION__ ) \ -<< " ERROR " \ -<< "\033[0m" << X << std::endl + std::cout << "\033[1;31m" << std::left << std::setw( FCNNAMELENGTH ) << detail::trimmedString( __PRETTY_FUNCTION__ ) \ + << " ERROR " \ + << "\033[0m" << X << std::endl /// @ingroup msgService macro FATAL /// Used for printing fatal errors messages, and will always be printed and will terminate the process afterwards. #define FATAL( X ) \ - { std::cout << "\033[1;31m" << std::left << std::setw( FCNNAMELENGTH ) << trimmedString( __PRETTY_FUNCTION__ ) \ -<< " FATAL " \ -<< "\033[0m" << X << std::endl; \ -throw std::runtime_error( trimmedString( __PRETTY_FUNCTION__)+ " FATAL" ) ;} +{ std::cout << "\033[1;31m" << std::left << std::setw( FCNNAMELENGTH ) << detail::trimmedString( __PRETTY_FUNCTION__ ) \ + << " FATAL " \ + << "\033[0m" << X << std::endl; \ + throw std::runtime_error( detail::trimmedString( __PRETTY_FUNCTION__)+ " FATAL" ) ;} /// @ingroup msgService macro FATAL /// Used for printing warning messages, can be switched off using WARNINGLEVEL. These messages are often harmless, but sometimes not! #ifdef WARNINGLEVEL #define WARNING( X ) \ - std::cout << "\033[1;35m" << std::left << std::setw( FCNNAMELENGTH ) << trimmedString( __PRETTY_FUNCTION__ ) \ -<< " WARNING " \ -<< "\033[0m" << X << std::endl + std::cout << "\033[1;35m" << std::left << std::setw( FCNNAMELENGTH ) << detail::trimmedString( __PRETTY_FUNCTION__ ) \ + << " WARNING " \ + << "\033[0m" << X << std::endl #else #define WARNING( X ) #endif -#ifdef TRACELEVEL -#define TRACE( X ) \ - std::cout << "\033[1;36m" << std::left << std::setw( FCNNAMELENGTH ) << trimmedString( __PRETTY_FUNCTION__ ) \ -<< " TRACE " \ -<< "\033[0m" << X << std::endl -#else -#define TRACE( X ) -#endif - #endif diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index 308f61833e3..3bba2f76609 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -21,7 +21,6 @@ #include "AmpGen/Tensor.h" #include "AmpGen/MinuitParameter.h" -#include "AmpGen/IntegratorSIMD.h" #include "TMatrixD.h" @@ -38,49 +37,47 @@ namespace AmpGen { public: #if ENABLE_AVX2 - using EventList_type = EventListSIMD; - using Integrator_type= IntegratorSIMD; - using complex_v = AVX2::complex_t; - using float_v = AVX2::float_t; + using EventList_type = EventListSIMD; #else using EventList_type = EventList; - using Integrator_type = Integrator; - using complex_v = complex_t; - using float_v = real_t; #endif PolarisedSum() = default; PolarisedSum(const EventType&, MinuitParameterSet&, const std::vector& = {}); void prepare(); - void setEvents(EventList&); - void setMC(EventList&); + void setEvents(EventList_type&); + void setMC(EventList_type&); + #if ENABLE_AVX2 + void setEvents(EventList& evts){ m_ownEvents = true; setEvents( *new EventList_type(evts)) ; }; + void setMC(EventList& evts){ setMC( *new EventList_type(evts)) ; }; + #endif + float_v operator()( const float_v*, const unsigned) const; + real_t operator()(const Event& evt) const; void reset(const bool& = false); void debug(const Event&); void debug_norm(); void setWeight(MinuitProxy); double getWeight() const; - void calculateNorms(); + void updateNorms(); void generateSourceCode(const std::string&, const double& = 1, bool = false); - void build_probunnormalised(); Expression probExpression(const Tensor&, const std::vector&, DebugSymbols* = nullptr) const; size_t size() const; real_t norm() const; complex_t norm(const size_t&, const size_t&, Integrator* = nullptr); - inline real_t operator()(const Event& evt) const { return m_weight * prob_unnormalised(evt) / m_norm; } - real_t prob_unnormalised(const Event&) const; - real_t prob(const Event&) const; - real_t getValNoCache(const Event&) ; + real_t getValNoCache(const Event&) const; std::vector fitFractions(const LinearErrorPropagator&); std::vector> matrixElements() const; void transferParameters(); Tensor transitionMatrix(); const TransitionMatrix& operator[](const size_t& i) const { return m_matrixElements[i] ; } - std::function evaluator(const EventList* = nullptr) const; - KeyedView componentEvaluator(const EventList* = nullptr) const; + std::function evaluator(const EventList_type* = nullptr) const; + KeyedView componentEvaluator(const EventList_type* = nullptr) const; private: size_t m_nCalls = {0}; real_t m_norm = {1}; - EventList* m_events = {nullptr}; + EventList_type* m_events = {nullptr}; + Store m_cache = {}; + bool m_ownEvents = {false}; MinuitParameterSet* m_mps = {nullptr}; MinuitProxy m_weight = {nullptr,1}; std::vector m_pVector = {}; @@ -94,9 +91,9 @@ namespace AmpGen std::vector m_integIndex; AmplitudeRules m_rules; std::pair m_dim; - std::vector> m_matrixElements; - CompiledExpression m_probExpression; - + std::vector> m_matrixElements; + CompiledExpression m_probExpression; + std::vector m_pdfCache; std::vector> indexProduct(const std::vector>&, const std::vector&) const; std::vector polarisations(const std::string&) const ; }; diff --git a/AmpGen/Store.h b/AmpGen/Store.h new file mode 100644 index 00000000000..594efb83ff9 --- /dev/null +++ b/AmpGen/Store.h @@ -0,0 +1,144 @@ +#ifndef AMPGEN_STORE_H +#define AMPGEN_STORE_H + +#include "AmpGen/simd/utils.h" +#include "AmpGen/EventList.h" + +namespace AmpGen { + + enum Alignment { + SoA, AoS + }; + + template class Store + { + public: + Store( const size_t& nEntries=0, const size_t& nFields=0) : + m_nEntries(nEntries), + m_nBlocks(utils::aligned_size( nEntries ) / utils::size::value ), + m_nFields(nFields), + m_store(m_nBlocks * m_nFields) {} + + template Store( const Store& store, const std::vector& functors, const size_t& fieldsPerFunctor=0) + : Store(store.size(), functors, fieldsPerFunctor){ + for( auto& f : functors ) update(store,f); + } + + template Store( const size_t& nEntries, const std::vector& functors, const size_t& fieldsPerFunctor = 0) + { + for(const auto& functor : functors) + { + auto vsize = fieldsPerFunctor == 0 ? functor.returnTypeSize() / sizeof(stored_type) : fieldsPerFunctor; + DEBUG("Registering: " << functor.name() << " I = " << m_nFields << " / " << functors.size() * vsize ); + m_index[ functor.name() ] = std::make_pair(m_nFields, vsize); + m_nFields += vsize; + } + m_nEntries = nEntries; + m_nBlocks = utils::aligned_size(nEntries)/utils::size::value; + m_store.resize(m_nBlocks * m_nFields); + } + + __always_inline stored_type operator[]( const size_t& index ) const { return m_store[index]; } + __always_inline stored_type& operator[]( const size_t& index ) { return m_store[index]; } + template unsigned find( const T& t ) const { return m_index.find( t.name() )->second.first; } + + __always_inline size_t size() const { return m_nEntries; } + __always_inline size_t nBlocks() const { return m_nBlocks; } + __always_inline size_t nFields() const { return m_nFields; } + __always_inline size_t aligned_size() const { return m_nBlocks * utils::size::value ; } + __always_inline const stored_type& operator()(const size_t& index, const size_t& field) const + { + if constexpr( align == Alignment::SoA ) return m_store[ field * m_nBlocks + index] ; + else return m_store[index*m_nFields+field]; + } + __always_inline const stored_type* data() const { return m_store.data(); } + __always_inline stored_type& operator()(const size_t& index, const size_t& field) + { + if constexpr( align == Alignment::SoA ) return m_store[ field * m_nBlocks + index] ; + else return m_store[index*m_nFields+field]; + } + + void resize(const size_t& nEntries, const size_t& nFields ) + { + m_nEntries = nEntries; + m_nBlocks = utils::aligned_size(nEntries)/utils::size::value; + m_nFields = nFields; + m_store.resize(m_nBlocks * m_nFields); + m_index.clear(); + } + void clear() { m_store.clear(); m_index.clear() ; } + void store( const size_t& event0, const size_t& index0, const stored_type* item, const unsigned N = 1 ) + { + if constexpr( align == Alignment::AoS ) + std::memcpy( &(*this)(event0, index0) , item, N * sizeof( stored_type ) ); + else + { + for( unsigned i = 0 ; i != N ; ++i ) (*this)(event0, index0 +i ) = item[i]; + } + } + + template void update(const Store& is, const functor_type& fcn) + { + auto f = m_index.find( fcn.name() ); + if( f == m_index.end() ) FATAL("Expression: " << fcn.name() << " is not registed"); + auto [p0, s] = f->second; + DEBUG("Updating: " << fcn.name() << " index = " << p0 << " size_of = " << s << " on store: " << is.size() << " blocks = " << is.nBlocks() << " fields = " << is.nFields () ); + if constexpr( align == Alignment::AoS ) + { + if constexpr( std::is_same< typename functor_type::return_type, void >::value ) + fcn.batch(aligned_size(), is.nFields(), m_nFields, nullptr, m_store.data() + p0, 1, fcn.externBuffer().data(), is.data()); + if constexpr( ! std::is_same< typename functor_type::return_type, void >::value ) + fcn.batch(aligned_size(), is.nFields(), m_nFields , m_store.data() + p0 , fcn.externBuffer().data(), is.data()); + } + else + { + if constexpr( std::is_same< typename functor_type::return_type, void >::value) + fcn.batch(aligned_size(), is.nFields(), 1, nullptr, m_store.data() + p0*m_nBlocks, m_nBlocks, fcn.externBuffer().data(), is.data() ); + else + fcn.batch(aligned_size(), is.nFields(), 1 , m_store.data() + p0*m_nBlocks , fcn.externBuffer().data(), is.data() ); + } + } + template void update( const EventList& events, const functor_type& fcn ) + { + auto f = m_index.find( fcn.name() ); + if( f == m_index.end() ) FATAL("Expression: " << fcn.name() << " is not registed"); + auto [p0, s] = f->second; + if constexpr( std::is_same< typename functor_type::return_type, void >::value ) + { + + #ifdef _OPENMP + #pragma omp parallel for + #endif + for ( size_t evt = 0; evt < events.size(); ++evt ) + { + std::vector buffer(s); + fcn(buffer.data(), 1, fcn.externBuffer().data(), events[evt].address() ); + store(evt, p0, buffer.data(), s ); + } + } + else { + #ifdef _OPENMP + #pragma omp parallel for + #endif + for ( size_t evt = 0; evt < events.size(); ++evt ){ + auto tmp = fcn( events[evt].address( ) ); + store( evt, p0, &tmp, s); + } + } + } + + private: + size_t m_nEntries{0}; /// Number of entries, i.e. number of events + size_t m_nBlocks {0}; /// Number of blocks, i.e. number of entries aligned to the size, divided by block size. + size_t m_nFields {0}; /// Number of fields per entry + std::vector m_store; + std::map> m_index; + }; +} +//using aos_store = AmpGen::Store; +//using soa_store = AmpGen::Store; +// +//ENABLE_DEBUG(aos_store) +//ENABLE_DEBUG(soa_store) + +#endif diff --git a/AmpGen/SumPDF.h b/AmpGen/SumPDF.h index 0bf34fa827e..cc0d466bca2 100644 --- a/AmpGen/SumPDF.h +++ b/AmpGen/SumPDF.h @@ -75,21 +75,19 @@ namespace AmpGen for_each( m_pdfs, []( auto& f ) { f.prepare(); } ); #pragma omp parallel for reduction( +: LL ) for ( unsigned int block = 0; block < m_events->nBlocks(); ++block ) { - LL += log(this->operator()(m_events->block(block), block)); + LL += m_events->weight(block) * log(this->operator()(m_events->block(block), block)); } return -2 * utils::sum_elements(LL); } #endif } /// Returns the probability for the given event. - #if ENABLE_AVX2 float_v operator()( const float_v* evt , const unsigned block) { float_v prob = 0.f; for_each( this->m_pdfs, [&prob, &evt,block]( const auto& f ) { prob += f(evt, block); } ); return prob; } - #endif /// Returns the probability for the given event. double operator()( const eventValueType& evt ) { diff --git a/AmpGen/simd/avx2_types.h b/AmpGen/simd/avx2_types.h index a9ec3e082ee..04579d4ad73 100644 --- a/AmpGen/simd/avx2_types.h +++ b/AmpGen/simd/avx2_types.h @@ -20,38 +20,11 @@ namespace AmpGen { float_t(const double& f ) : data( _mm256_set1_ps( float(f) )) {} float_t(const float* f ) : data( _mm256_loadu_ps( f ) ) {} void store( float* ptr ) const { _mm256_storeu_ps( ptr, data ); } - std::array to_array() const { std::array b; store( &b[0] ); return b; } + std::array to_array() const { std::array b; store( &b[0] ); return b; } float at(const unsigned i) const { return to_array()[i] ; } operator __m256() const { return data ; } }; - - struct complex_t { - float_t re; - float_t im; - typedef std::complex scalar_type; - static constexpr unsigned size = 8 ; - - float_t real() const { return re; } - float_t imag() const { return im; } - complex_t() = default; - complex_t( const float_t& re, const float_t& im) : re(re), im(im) {} - complex_t( const float& re, const float& im) : re(re), im(im) {} - complex_t( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} - complex_t( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} - const std::complex at(const unsigned i) const { return std::complex(re.to_array()[i], im.to_array()[i]) ; } - void store( float* sre, float* sim ){ re.store(sre); im.store(sim); } - void store( std::complex* r ){ - auto re_arr = re.to_array(); - auto im_arr = im.to_array(); - for( unsigned i = 0 ; i != float_t::size; ++i ) r[i] = std::complex( re_arr[i], im_arr[i] ); - } - }; - - inline std::ostream& operator<<( std::ostream& os, const float_t& obj ) { - auto buffer = obj.to_array(); - for( unsigned i = 0 ; i != float_t::size; ++i ) os << buffer[i] << " "; - return os; - } + inline float_t operator+( const float_t& lhs, const float_t& rhs ) { return _mm256_add_ps(lhs, rhs); } inline float_t operator-( const float_t& lhs, const float_t& rhs ) { return _mm256_sub_ps(lhs, rhs); } inline float_t operator*( const float_t& lhs, const float_t& rhs ) { return _mm256_mul_ps(lhs, rhs); } @@ -80,13 +53,45 @@ namespace AmpGen { inline float_t select(const float_t& mask, const float_t& a, const float_t& b ) { return _mm256_blendv_ps( b, a, mask ); } inline float_t select(const bool& mask , const float_t& a, const float_t& b ) { return mask ? a : b; } inline float_t atan2( const float_t& y, const float_t& x ){ - std::array bx{x.to_array()}, by{y.to_array()}, rt; - for( unsigned i = 0 ; i != float_t::size ; ++i ) rt[i] = std::atan2( by[i] , bx[i] ); + std::array bx{x.to_array()}, by{y.to_array()}, rt; + for( unsigned i = 0 ; i != 8 ; ++i ) rt[i] = std::atan2( by[i] , bx[i] ); return float_t (rt.data() ); } + inline float_t fmadd( const float_t& a, const float_t& b, const float_t& c ) + { + return _mm256_fmadd_ps(a, b, c ); + } + struct complex_t { + float_t re; + float_t im; + typedef std::complex scalar_type; + + float_t real() const { return re; } + float_t imag() const { return im; } + float_t norm() const { return re*re + im *im ; } + complex_t() = default; + complex_t( const float_t& re, const float_t& im) : re(re), im(im) {} + complex_t( const float& re, const float& im) : re(re), im(im) {} + complex_t( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} + complex_t( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} + const std::complex at(const unsigned i) const { return std::complex(re.to_array()[i], im.to_array()[i]) ; } + void store( float* sre, float* sim ){ re.store(sre); im.store(sim); } + void store( std::complex* r ){ + auto re_arr = re.to_array(); + auto im_arr = im.to_array(); + for( unsigned i = 0 ; i != re_arr.size(); ++i ) r[i] = std::complex( re_arr[i], im_arr[i] ); + } + }; + + inline std::ostream& operator<<( std::ostream& os, const float_t& obj ) { + auto buffer = obj.to_array(); + for( unsigned i = 0 ; i != 8; ++i ) os << buffer[i] << " "; + return os; + } inline float_t real(const complex_t& arg ){ return arg.re ; } inline float_t imag(const complex_t& arg ){ return arg.im ; } inline complex_t conj(const complex_t& arg ){ return complex_t(arg.re, -arg.im) ; } + inline float_t conj(const float_t& arg ){ return arg ; } inline complex_t operator+( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re + rhs, lhs.im); } inline complex_t operator-( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re - rhs, lhs.im); } inline complex_t operator*( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re*rhs, lhs.im*rhs); } diff --git a/AmpGen/simd/avx2d_types.h b/AmpGen/simd/avx2d_types.h new file mode 100644 index 00000000000..594b95dcedc --- /dev/null +++ b/AmpGen/simd/avx2d_types.h @@ -0,0 +1,152 @@ +#ifndef AMPGEN_AVXd_TYPES +#define AMPGEN_AVXd_TYPES 1 + +#include +#include +#include +#include +#include "AmpGen/simd/avx_mathfun.h" +#include + +namespace AmpGen { + namespace AVX2d { + struct float_t { + __m256d data; + static constexpr unsigned size = 4; + typedef double scalar_type; + float_t() = default; + float_t(__m256d data ) : data(data) {} + float_t(const double& f ) : data( _mm256_set1_pd( f )) {} + float_t(const double* f ) : data( _mm256_loadu_pd( f ) ) {} + void store( double* ptr ) const { _mm256_storeu_pd( ptr, data ); } + std::array to_array() const { std::array b; store( &b[0] ); return b; } + double at(const unsigned i) const { return to_array()[i] ; } + operator __m256d() const { return data ; } + }; + + inline float_t operator+( const float_t& lhs, const float_t& rhs ) { return _mm256_add_pd(lhs, rhs); } + inline float_t operator-( const float_t& lhs, const float_t& rhs ) { return _mm256_sub_pd(lhs, rhs); } + inline float_t operator*( const float_t& lhs, const float_t& rhs ) { return _mm256_mul_pd(lhs, rhs); } + inline float_t operator/( const float_t& lhs, const float_t& rhs ) { return _mm256_div_pd(lhs, rhs); } + inline float_t operator-( const float_t& x ) { return -1.f * x; } + inline float_t operator&( const float_t& lhs, const float_t& rhs ) { return _mm256_and_pd( lhs, rhs ); } + inline float_t operator|( const float_t& lhs, const float_t& rhs ) { return _mm256_or_pd( lhs, rhs ); } + inline float_t operator^( const float_t& lhs, const float_t& rhs ) { return _mm256_xor_pd( lhs, rhs ); } + inline float_t operator+=(float_t& lhs, const float_t& rhs ){ lhs = lhs + rhs; return lhs; } + inline float_t operator-=(float_t& lhs, const float_t& rhs ){ lhs = lhs - rhs; return lhs; } + inline float_t operator*=(float_t& lhs, const float_t& rhs ){ lhs = lhs * rhs; return lhs; } + inline float_t operator/=(float_t& lhs, const float_t& rhs ){ lhs = lhs / rhs; return lhs; } + inline float_t operator&&( const float_t& lhs, const float_t& rhs ) { return _mm256_and_pd( lhs, rhs ); } + inline float_t operator||( const float_t& lhs, const float_t& rhs ) { return _mm256_or_pd( lhs, rhs ); } + inline float_t operator!( const float_t& x ) { return x ^ _mm256_castsi256_pd( _mm256_set1_epi32( -1 ) ); } + inline float_t operator<( const float_t& lhs, const float_t& rhs ) { return _mm256_cmp_pd( lhs, rhs, _CMP_LT_OS ); } + inline float_t operator>( const float_t& lhs, const float_t& rhs ) { return _mm256_cmp_pd( lhs, rhs, _CMP_GT_OS ); } + inline float_t operator==( const float_t& lhs, const float_t& rhs ){ return _mm256_cmp_pd( lhs, rhs, _CMP_EQ_OS ); } + inline float_t sqrt( const float_t& v ) { return _mm256_sqrt_pd(v); } + // inline float_t sin( const float_t& v ) { return sin256_pd(v) ; } + // inline float_t cos( const float_t& v ) { return cos256_pd(v) ; } + // inline float_t tan( const float_t& v ) { float_t s; float_t c; sincos256_pd(v, (__m256*)&s, (__m256*)&c) ; return s/c; } + // inline float_t log( const float_t& v ) { return log256_ps(v) ; } + // inline float_t exp( const float_t& v ) { return exp256_ps(v) ; } + inline float_t abs ( const float_t& v ) { + static const __m256d sign_mask = _mm256_set1_pd(-0.); // -0. = 1 << 63 + return _mm256_andnot_pd(sign_mask, v); + } + inline float_t select(const float_t& mask, const float_t& a, const float_t& b ) { return _mm256_blendv_pd( b, a, mask ); } + inline float_t select(const bool& mask , const float_t& a, const float_t& b ) { return mask ? a : b; } + inline float_t atan2( const float_t& y, const float_t& x ){ + std::array bx{x.to_array()}, by{y.to_array()}, rt; + for( unsigned i = 0 ; i != 4 ; ++i ) rt[i] = std::atan2( by[i] , bx[i] ); + return float_t (rt.data() ); + } + inline float_t log( const float_t& x ) + { + std::array bx{x.to_array()}, rt; + for( unsigned i = 0 ; i != 4 ; ++i ) rt[i] = std::log(bx[i]); + return float_t (rt.data()); + } + + struct complex_t { + float_t re; + float_t im; + typedef std::complex scalar_type; + + float_t real() const { return re; } + float_t imag() const { return im; } + float_t norm() const { return re*re + im *im ; } + complex_t() = default; + complex_t( const float_t& re, const float_t& im) : re(re), im(im) {} + complex_t( const float& re, const float& im) : re(re), im(im) {} + complex_t( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} + complex_t( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} + const std::complex at(const unsigned i) const { return std::complex(re.to_array()[i], im.to_array()[i]) ; } + void store( double* sre, double* sim ){ re.store(sre); im.store(sim); } + void store( scalar_type* r ) const { + auto re_arr = re.to_array(); + auto im_arr = im.to_array(); + for( unsigned i = 0 ; i != re_arr.size(); ++i ) r[i] = scalar_type( re_arr[i], im_arr[i] ); + } + auto to_array() const + { + std::array rt; + store( rt.data() ); + return rt; + } + }; + + inline std::ostream& operator<<( std::ostream& os, const float_t& obj ) { + auto buffer = obj.to_array(); + for( unsigned i = 0 ; i != 4; ++i ) os << buffer[i] << " "; + return os; + } + inline float_t real(const complex_t& arg ){ return arg.re ; } + inline float_t imag(const complex_t& arg ){ return arg.im ; } + inline complex_t conj(const complex_t& arg ){ return complex_t(arg.re, -arg.im) ; } + inline float_t conj(const float_t& arg ){ return arg ; } + inline complex_t operator+( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re + rhs, lhs.im); } + inline complex_t operator-( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re - rhs, lhs.im); } + inline complex_t operator*( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re*rhs, lhs.im*rhs); } + inline complex_t operator/( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re/rhs, lhs.im/rhs); } + inline complex_t operator+( const float_t& lhs, const complex_t& rhs ) { return complex_t(lhs + rhs.re, rhs.im); } + inline complex_t operator-( const float_t& lhs, const complex_t& rhs ) { return complex_t(lhs - rhs.re, - rhs.im); } + inline complex_t operator*( const float_t& lhs, const complex_t& rhs ) { return complex_t(lhs*rhs.re, lhs*rhs.im); } + inline complex_t operator/( const float_t& lhs, const complex_t& rhs ) { return complex_t( lhs * rhs.re , -lhs *rhs.im) / (rhs.re * rhs.re + rhs.im * rhs.im ); } + inline complex_t operator+( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re + rhs.re, lhs.im + rhs.im); } + inline complex_t operator-( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re - rhs.re, lhs.im - rhs.im); } + inline complex_t operator*( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re*rhs.re - lhs.im*rhs.im, lhs.re*rhs.im + lhs.im*rhs.re); } + inline complex_t operator/( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re*rhs.re + lhs.im*rhs.im, -lhs.re*rhs.im + lhs.im*rhs.re) / (rhs.re * rhs.re + rhs.im * rhs.im ); } + inline complex_t operator-( const complex_t& x ) { return -1.f * x; } + inline float_t abs( const complex_t& v ) { return sqrt( v.re * v.re + v.im * v.im ) ; } + inline float_t norm( const complex_t& v ) { return ( v.re * v.re + v.im * v.im ) ; } + inline complex_t select(const float_t& mask, const complex_t& a, const complex_t& b ) { return complex_t( select(mask, a.re, b.re), select(mask, a.im, b.im ) ) ; } + inline complex_t select(const float_t& mask, const float_t& a, const complex_t& b ) { return complex_t( select(mask, a , b.re), select(mask, 0.f, b.im) ); } + inline complex_t select(const float_t& mask, const complex_t& a, const float_t& b ) { return complex_t( select(mask, a.re, b ) , select(mask, a.im, 0.f) ); } + inline complex_t select(const bool& mask , const complex_t& a, const complex_t& b ) { return mask ? a : b; } + inline complex_t exp( const complex_t& v ){ + // float_t s; float_t c; sincos256_ps(v.im, (__m256*)&s, (__m256*)&c); + auto vr = v.re.to_array(); + auto vi = v.im.to_array(); + std::array rt_re; + std::array rt_im; + for( unsigned i = 0 ; i != 4; ++i ){ + rt_re[i] = std::exp( vr[i] ) * cos( vi[i] ); + rt_im[i] = std::exp( vr[i] ) * sin( vi[i] ); + // rt[i] = complex_t( exp(vr[i]) * cos(vi[i]), exp(vr[i]) * sin( vi[i] ) ); + } + return complex_t( rt_re.data(), rt_im.data() ); + } + inline float_t fmadd( const float_t& a, const float_t& b, const float_t& c ) + { + return _mm256_fmadd_pd(a, b, c ); + } + + inline std::ostream& operator<<( std::ostream& os, const complex_t& obj ) { return os << "( "<< obj.re << ") (" << obj.im << ")"; } + #pragma omp declare reduction(+: float_t: \ + omp_out = omp_out + omp_in) + #pragma omp declare reduction(+: complex_t: \ + omp_out = omp_out + omp_in) + + } +} + +#endif diff --git a/AmpGen/simd/iterator.h b/AmpGen/simd/iterator.h index 44e115f9b7d..3949a0a44ea 100644 --- a/AmpGen/simd/iterator.h +++ b/AmpGen/simd/iterator.h @@ -7,6 +7,7 @@ namespace AmpGen { std::array m_buffer; size_t m_pos{0}; public: + int pos() const { return m_pos ; } scatter_iterator( const size_t& pos, store_type* store ) : m_store(store), m_pos(pos) { @@ -36,6 +37,7 @@ namespace AmpGen { } bool operator==( const scatter_iterator& rhs ) const { return m_pos == rhs.m_pos ; } bool operator!=( const scatter_iterator& rhs ) const { return m_pos != rhs.m_pos ; } + friend int operator-( const scatter_iterator& lhs, const scatter_iterator& rhs) { return lhs.pos() - rhs.pos() ; } }; template auto make_scatter_iterator( const unsigned& pos, store_type* store) { diff --git a/AmpGen/simd/utils.h b/AmpGen/simd/utils.h index b8b5032a5e2..094877931b2 100644 --- a/AmpGen/simd/utils.h +++ b/AmpGen/simd/utils.h @@ -1,13 +1,49 @@ +#ifndef AMPGEN_SIMD_UTILS_H +#define AMPGEN_SIMD_UTILS_H + #include -#include "AmpGen/simd/avx2_types.h" +#if ENABLE_AVX2 +#if DOUBLE_PRECISION + #include "AmpGen/simd/avx2d_types.h" +#else + #include "AmpGen/simd/avx2_types.h" +#endif +#endif namespace AmpGen { - namespace utils { +#if ENABLE_AVX2 +#if DOUBLE_PRECISION + using float_v = AVX2d::float_t; + using complex_v = AVX2d::complex_t; +#else + using float_v = AVX2::float_t; + using complex_v = AVX2::complex_t; +#endif +#else + using float_v = double; + using complex_v = std::complex; +#endif - template struct is_vector_type { static constexpr bool value = false; }; - template <> struct is_vector_type { static constexpr bool value = true ; }; - template <> struct is_vector_type { static constexpr bool value = true ; }; + namespace utils { + template struct is_vector_type : std::false_type {}; + template struct size { static constexpr unsigned value = 1; } ; +#if ENABLE_AVX2 +#if DOUBLE_PRECISION + template <> struct is_vector_type : std::true_type {}; + template <> struct is_vector_type : std::true_type {}; + template <> struct size { static constexpr unsigned value = 4; }; + template <> struct size { static constexpr unsigned value = 4; }; +#else + template <> struct is_vector_type : std::true_type {}; + template <> struct is_vector_type : std::true_type {}; + template <> struct size { static constexpr unsigned value = 8; }; + template <> struct size { static constexpr unsigned value = 8; }; +#endif +#else + template <> struct is_vector_type : std::false_type {}; + template <> struct is_vector_type : std::false_type {}; +#endif template simd_type gather( const container_type& container, const functor_type& functor, unsigned offset=0, float df =0.) { @@ -20,7 +56,7 @@ namespace AmpGen { } template size_t aligned_size( const size_t& unaligned_size ) { - return simd_type::size * unsigned ( 1 + (unaligned_size -1 ) / simd_type::size ); + return size::value * unsigned ( 1 + (unaligned_size -1 ) / size::value ); } template auto sum_elements( const simd_type& obj ) { @@ -28,15 +64,43 @@ namespace AmpGen { { auto arr = obj.to_array(); auto rt = arr[0]; - for( unsigned i = 1 ; i != simd_type::size; ++i ) rt = rt + arr[i]; + for( unsigned i = 1 ; i != size::value; ++i ) rt = rt + arr[i]; return rt; } else return obj; } - template auto get( vtype v ){ + template auto get( vtype v ) + { if constexpr ( is_vector_type::value ) return v.at(p); if constexpr ( ! is_vector_type::value ) return v; - } - + } + template < class vtype> auto at( vtype v, const unsigned p=0 ) + { + if constexpr ( is_vector_type::value ) return v.at(p); + if constexpr ( ! is_vector_type::value ) return v; + } + template auto norm( const ctype& v ) + { + #if ENABLE_AVX2 && DOUBLE_PRECISION + if constexpr( is_vector_type::value ) return AVX2d::norm(v); + #endif + #if ENABLE_AVX2 && ! DOUBLE_PRECISION + if constexpr( is_vector_type::value ) return AVX2::norm(v); + #endif + if constexpr( ! is_vector_type::value ) return std::norm(v); + } + template void store( store_type* container, const type& v) + { + if constexpr( is_vector_type::value ) + { + auto arr = v.to_array(); + for( unsigned k = 0 ; k != utils::size::value; ++k ) container[k] = arr[k]; + } + else { + *container = v; + } + } } } + +#endif diff --git a/Standalone.cmake b/Standalone.cmake index a0047390f44..f0248d9c909 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -13,7 +13,8 @@ if( NOT "${CMAKE_CXX_STANDARD}" ) endif() SET(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") -SET(ENABLE_AVX2 TRUE CACHE BOOL "ENABLE_AVX2") +SET(ENABLE_AVX2 FALSE CACHE BOOL "ENABLE_AVX2") +SET(PRECISION "DOUBLE" CACHE STRING "PRECISION") set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -152,9 +153,15 @@ target_compile_options(AmpGen -Wno-unknown-pragmas $<$:-O3>) -if( ENABLE_AVX2 ) - message(STATUS "Enabling AVX2...") - target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX2=1") +if( ENABLE_AVX2 ) + if( "${PRECISION}" MATCHES "DOUBLE" ) + message(STATUS "Enabling AVX2 [double precision]") + target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX2=1" "DOUBLE_PRECISION=1") + elseif( "${PRECISION}" MATCHES "SINGLE" ) + message(STATUS "Enabling AVX2 [single precision]") + target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX2=1" "DOUBLE_PRECISION=0") + + endif() target_compile_options(AmpGen PUBLIC -march=native -ftree-vectorize -mavx2 -DHAVE_AVX2_INSTRUCTIONS) endif() diff --git a/apps/ConvertToSourceCode.cpp b/apps/ConvertToSourceCode.cpp index c753204bb7c..c6864aca788 100644 --- a/apps/ConvertToSourceCode.cpp +++ b/apps/ConvertToSourceCode.cpp @@ -91,7 +91,7 @@ template void generate_source(T& pdf, EventList& normEvents, const std mps["Pz"]->setCurrentFitVal(pz); pdf.transferParameters(); } - double n = pdf.prob_unnormalised( evt ); + double n = pdf(evt); if ( n > pMax ) pMax = n; } norm = pMax * sf ; diff --git a/apps/Debugger.cpp b/apps/Debugger.cpp index 29a1c2346a5..a19f3f83563 100644 --- a/apps/Debugger.cpp +++ b/apps/Debugger.cpp @@ -49,16 +49,17 @@ void invertParity( Event& event, const size_t& nParticles) template < class FCN > void debug( FCN& sig, EventList& accepted, bool verbose, TRandom3* rndm, MinuitParameterSet& mps ){ INFO("Debugging: "); + unsigned eventToDebug = 0; sig.setEvents( accepted ); sig.prepare(); - sig.debug( accepted[0] ); - accepted[0].print(); + sig.debug( accepted[eventToDebug] ); + accepted[eventToDebug].print(); // if( verbose ) print( accepted[0], sig.matrixElements(), verbose ); - invertParity(accepted[0], accepted.eventType().size() ); - accepted[0].print(); + invertParity(accepted[eventToDebug], accepted.eventType().size() ); + accepted[eventToDebug].print(); sig.reset(); sig.prepare(); - sig.debug( accepted[0] ); + sig.debug( accepted[eventToDebug] ); } int main( int argc, char** argv ) @@ -93,11 +94,10 @@ int main( int argc, char** argv ) if( infile == "" ){ for( unsigned i = 0 ; i != 16; ++i ){ Event evt = PhaseSpace( eventType, rndm ).makeEvent(); + evt.setIndex(i); accepted.push_back(evt); } } - accepted[0].print(); - std::string type = NamedParameter("Type","CoherentSum"); if( type == "PolarisedSum") diff --git a/apps/Generator.cpp b/apps/Generator.cpp index 89bbb6d2cba..3abf40b7bb6 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -41,7 +41,7 @@ struct FixedLibPDF { void prepare(){}; void setEvents( AmpGen::EventList& evts ){}; - double prob_unnormalised( const AmpGen::Event& evt ) const { return PDF( evt, 1 ); } + double operator()( const AmpGen::Event& evt ) const { return PDF( evt, 1 ); } FixedLibPDF( const std::string& lib ) { void* handle = dlopen( lib.c_str(), RTLD_NOW ); diff --git a/examples/FitterWithPolarisation.cpp b/examples/FitterWithPolarisation.cpp index 8ee80173425..69b39fd171f 100644 --- a/examples/FitterWithPolarisation.cpp +++ b/examples/FitterWithPolarisation.cpp @@ -32,10 +32,18 @@ #include #include +#if ENABLE_AVX2 + #include "AmpGen/EventListSIMD.h" + using EventList_type = AmpGen::EventListSIMD; +#else + #include "AmpGen/EventList.h" + using EventList_type = AmpGen::EventList; +#endif + using namespace AmpGen; template -FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& MPS ); +FitResult* doFit( PDF&& pdf, EventList_type& data, EventList_type& mc, MinuitParameterSet& MPS ); int main( int argc, char* argv[] ) { @@ -79,6 +87,7 @@ int main( int argc, char* argv[] ) the parsed options. For historical reasons, this is referred to as loading it from a "Stream" */ MinuitParameterSet MPS; MPS.loadFromStream(); + for( auto& p : MPS ) if( p->flag() == Flag::Free ) p->setResult( gRandom->Gaus( p->mean(), p->err() ), p->err(), 0,0 ); /* An EventType specifies the initial and final state particles as a vector that will be described by the fit. It is typically loaded from the interface parameter EventType. */ @@ -94,12 +103,12 @@ int main( int argc, char* argv[] ) /* Events are read in from ROOT files. If only the filename and the event type are specified, the file is assumed to be in the specific format that is defined by the event type, unless the branches to load are specified in the user options */ - EventList events(dataFile, evtType, Branches(bNames), GetGenPdf(false) ); + EventList_type events(dataFile, evtType, Branches(bNames), GetGenPdf(false) ); /* Generate events to normalise the PDF with. This can also be loaded from a file, which will be the case when efficiency variations are included. Default number of normalisation events is 2 million. */ - EventList eventsMC = Generator<>(evtType, &rndm).generate(int(2e6)); + EventList_type eventsMC = Generator<>(evtType, &rndm).generate(int(2e6)); sig.setMC( eventsMC ); @@ -107,7 +116,7 @@ int main( int argc, char* argv[] ) /* Do the fit and return the fit results, which can be written to the log and contains the covariance matrix, fit parameters, and other observables such as fit fractions */ - FitResult* fr = doFit(make_pdf(sig), events, eventsMC, MPS ); + FitResult* fr = doFit(make_pdf(sig), events, eventsMC, MPS ); /* Calculate the `fit fractions` using the signal model and the error propagator (i.e. fit results + covariance matrix) of the fit result, and write them to a file. */ @@ -116,20 +125,12 @@ int main( int argc, char* argv[] ) INFO("Adding fraction to file..."); fr->addFractions( fitFractions ); INFO("Writing file ... "); - fr->writeToFile( logFile ); - output->cd(); - - /* Write out the data plots. This also shows the first example of the named arguments - to functions, emulating python's behaviour in this area */ - - auto plots = events.makeDefaultProjections(PlotOptions::Prefix("Data"), PlotOptions::Bins(100)); - for ( auto& plot : plots ) plot->Write(); - + fr->writeToFile( logFile ); output->Close(); } template -FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& MPS ) +FitResult* doFit( PDF&& pdf, EventList_type& data, EventList_type& mc, MinuitParameterSet& MPS ) { auto time_wall = std::chrono::high_resolution_clock::now(); auto time = std::clock(); @@ -166,6 +167,18 @@ FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& double tWall = std::chrono::duration( twall_end - time_wall ).count(); INFO( "Wall time = " << tWall / 1000. ); INFO( "CPU time = " << time_cpu ); + auto evaluator = pdf.componentEvaluator(&mc); + auto projections = data.eventType().defaultProjections(100); + + /* Write out the data plots. This also shows the first example of the named arguments + to functions, emulating python's behaviour in this area */ + + for( const auto& proj : projections ) + { + proj(mc, evaluator, PlotOptions::Norm(data.size()), PlotOptions::AutoWrite() ); + //proj(mc, evaluator_per_component, PlotOptions::Prefix("amp"), PlotOptions::Norm(data.size()), PlotOptions::AutoWrite() ); + proj(data, PlotOptions::Prefix("Data") )->Write(); + } fr->print(); return fr; } diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp index 48878c4a5a3..f40a90331e7 100644 --- a/examples/QcGenerator.cpp +++ b/examples/QcGenerator.cpp @@ -184,7 +184,7 @@ template class Psi3770 { DTEventList generate( const size_t& N ) { DTEventList output( m_signalType, m_tagType ); - ProgressBar pb(60, trimmedString(__PRETTY_FUNCTION__)); + ProgressBar pb(60, detail::trimmedString(__PRETTY_FUNCTION__)); auto tStartTotal = std::chrono::high_resolution_clock::now(); int currentSize = 0; double norm = -1; diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 9ad5a6629c8..e74de1ba47a 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -28,7 +28,7 @@ #include "AmpGen/simd/utils.h" #ifdef _OPENMP - #include +#include #endif using namespace AmpGen; @@ -36,12 +36,12 @@ CoherentSum::CoherentSum() = default; CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, const std::string& prefix ) : m_rules (mps) - , m_evtType (type) - , m_printFreq(NamedParameter( "CoherentSum::PrintFrequency", 100) ) - , m_dbThis (NamedParameter( "CoherentSum::Debug" , false)) - , m_verbosity(NamedParameter( "CoherentSum::Verbosity" , 0) ) + , m_evtType (type) + , m_printFreq(NamedParameter( "CoherentSum::PrintFrequency", 100) ) + , m_dbThis (NamedParameter( "CoherentSum::Debug" , false)) + , m_verbosity(NamedParameter( "CoherentSum::Verbosity" , 0) ) , m_objCache (NamedParameter("CoherentSum::ObjectCache" ,"") ) - , m_prefix (prefix) + , m_prefix (prefix) { auto amplitudes = m_rules.getMatchingRules( m_evtType, prefix); if( amplitudes.size() == 0 ){ @@ -52,90 +52,74 @@ CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, m_normalisations.resize( m_matrixElements.size(), m_matrixElements.size() ); size_t nThreads = NamedParameter ("nCores" , std::thread::hardware_concurrency(), "Number of threads to use" ); ThreadPool tp(nThreads); + //#pragma omp parallel for for(size_t i = 0; i < m_matrixElements.size(); ++i){ tp.enqueue( [i,this,&mps,&litudes]{ - m_matrixElements[i] = TransitionMatrix( amplitudes[i].first, amplitudes[i].second, mps, this->m_evtType.getEventFormat(), this->m_dbThis); - CompilerWrapper().compile( m_matrixElements[i].amp, this->m_objCache); } ); + m_matrixElements[i] = TransitionMatrix( amplitudes[i].first, amplitudes[i].second, mps, this->m_evtType.getEventFormat(), this->m_dbThis); + CompilerWrapper().compile( m_matrixElements[i], this->m_objCache); } ); } - m_isConstant = false; } void CoherentSum::prepare() { - if ( m_isConstant && m_prepareCalls != 0 ) return; transferParameters(); - std::vector changedPdfIndices; ProfileClock clockEval; - if( m_prepareCalls == 0 && m_events != nullptr ){ - m_events->reserveCache(m_matrixElements.size()); - for( auto& me : m_matrixElements ) me.addressData = m_events->registerExpression( me.amp ); - } - if( m_prepareCalls == 0 ) m_integrator.allocate( m_matrixElements ); - for ( size_t i = 0; i < m_matrixElements.size(); ++i ) { - m_matrixElements[i].amp.prepare(); - if ( m_prepareCalls != 0 && !m_matrixElements[i].amp.hasExternalsChanged() ) continue; - if ( m_events != nullptr ) m_events->updateCache( m_matrixElements[i].amp, m_matrixElements[i].addressData ); - m_integrator.prepareExpression(m_matrixElements[i].amp ); - changedPdfIndices.push_back(i); - m_matrixElements[i].amp.resetExternals(); + for (auto& t : m_matrixElements ) { + t.prepare(); + if ( m_prepareCalls != 0 && !t.hasExternalsChanged() ) continue; + if ( m_events != nullptr ) m_cache.update(m_events->store(), t ); + m_integrator.updateCache(t); + t.resetExternals(); + t.workToDo = true; } clockEval.stop(); ProfileClock clockIntegral; - if ( m_integrator.isReady()) updateNorms( changedPdfIndices ); + if ( m_integrator.isReady()) updateNorms(); else if ( m_verbosity ) WARNING( "No simulated sample specified for " << this ); - m_norm = norm(); - if ( m_prepareCalls == 0 ){ - INFO( "Norm: " << m_norm ); - for(unsigned i = 0 ; i != m_matrixElements.size() ; ++i ){ - for(unsigned j = 0 ; j != m_matrixElements.size() ; ++j ){ - if( std::isnan( std::real(m_normalisations(i,j) )) || std::isnan( std::imag(m_normalisations(i,j))) ) - ERROR("Norm: " << m_matrixElements[i].name() << " " << m_matrixElements[j].name() << " is ill-posed!"); - } - } - // INFO( m_normalisations.get(0,0) << " " - // << m_normalisations.get(1,0) << " " - // << m_normalisations.get(0,1) << " " - // << m_normalisations.get(2,2) ); - } - if ( m_verbosity && changedPdfIndices.size() !=0 ) { - clockIntegral.stop(); + clockIntegral.stop(); + if ( m_verbosity && m_prepareCalls % 100 == 0 ) { INFO( "Time Performance: " << "Eval = " << clockEval << " ms" << ", Integral = " << clockIntegral << " ms" << ", Total = " << clockEval + clockIntegral << " ms; normalisation = " << m_norm ); m_lastPrint = m_prepareCalls; } + for( auto& t : m_matrixElements ) t.workToDo = false; m_prepareCalls++; } -void CoherentSum::updateNorms( const std::vector& changedPdfIndices ) +void CoherentSum::updateNorms() { std::vector cacheIndex; std::transform( m_matrixElements.begin(), m_matrixElements.end(), std::back_inserter(cacheIndex), - [this](auto& m){ return this->m_integrator.getCacheIndex( m.amp ) ; } ); - for ( auto& i : changedPdfIndices ) - for ( size_t j = 0; j < size(); ++j ) - m_integrator.queueIntegral( cacheIndex[i], cacheIndex[j] ,i, j, &m_normalisations ); + [this](auto& m){ return this->m_integrator.getCacheIndex( m ) ; } ); + if(std::any_of(m_matrixElements.begin(),m_matrixElements.end(), [](auto& me){ return me.workToDo; } )) + { + for ( unsigned i = 0; i != m_matrixElements.size(); ++i ) + for ( size_t j = i; j < size(); ++j ){ + if( m_matrixElements[i].workToDo || m_matrixElements[j].workToDo ) + m_integrator.queueIntegral( cacheIndex[i], cacheIndex[j] ,i, j, &m_normalisations ); + } + } m_integrator.flush(); m_normalisations.resetCalculateFlags(); + m_norm = norm(); } void CoherentSum::debug( const Event& evt, const std::string& nameMustContain ) { prepare(); - for ( auto& me : m_matrixElements ) me.amp.resetExternals(); - if ( nameMustContain == "" ) - for ( auto& me : m_matrixElements ) { - auto A = me(evt); - INFO( std::setw(70) << me.decayTree.uniqueString() - << " A = [ " << utils::get(A.real()) << " " << utils::get(A.imag()) - << " ] g = [ "<< me.coupling().real() << " " << me.coupling().imag() << " ] " - << m_events->cache( evt.index(), me.addressData ) - << me.decayTree.CP() ); - - // if( m_dbThis ) me.amp.debug( evt.address() ); - } + for ( auto& me : m_matrixElements ) { + auto A = me(evt); + INFO( std::setw(70) << me.decayTree.uniqueString() + << " A = [ " << utils::get<0>(A.real()) << " " << utils::get<0>(A.imag()) + << " ] g = [ "<< me.coupling().real() << " " << me.coupling().imag() << " ] " + << m_cache( evt.index(), std::distance(&m_matrixElements[0], &me ) ) + << me.decayTree.CP() ); + + // if( m_dbThis ) me.amp.debug( evt.address() ); + } //else // for ( auto& me : m_matrixElements ) // if ( me.amp.name().find( nameMustContain ) != std::string::npos ) me.amp.debug( evt.address() ); @@ -169,8 +153,8 @@ std::vector CoherentSum::fitFractions(const LinearErrorPropagator& for ( size_t j = i + 1; j < ffForHead.size(); ++j ) { iCalc.emplace_back(ffForHead[i].name() + "x" + ffForHead[j].name(), - processIndex(m_matrixElements, ffForHead[i].name()), - processIndex(m_matrixElements, ffForHead[j].name()) ); + processIndex(m_matrixElements, ffForHead[i].name()), + processIndex(m_matrixElements, ffForHead[j].name()) ); } } std::vector interferenceFractions = iCalc(m_evtType.mother()+"_interference",linProp); @@ -191,16 +175,16 @@ void CoherentSum::generateSourceCode(const std::string& fname, const double& nor bool includePythonBindings = NamedParameter("CoherentSum::IncludePythonBindings",false); for ( auto& p : m_matrixElements ){ - stream << p.amp << std::endl; - p.amp.compileWithParameters( stream ); - if( includePythonBindings ) p.amp.compileDetails( stream ); + stream << p << std::endl; + p.compileWithParameters( stream ); + if( includePythonBindings ) p.compileDetails( stream ); } Expression event = Parameter("x0",0,true); Expression pa = Parameter("double(x1)",0,true); Expression amplitude; for( unsigned int i = 0 ; i < size(); ++i ){ auto& p = m_matrixElements[i]; - Expression this_amplitude = p.coupling() * Function( programatic_name( p.amp.name() ) + "_wParams", {event} ); + Expression this_amplitude = p.coupling() * Function( programatic_name( p.name() ) + "_wParams", {event} ); amplitude = amplitude + ( p.decayTree.finalStateParity() == 1 ? 1 : pa ) * this_amplitude; } stream << CompiledExpression(const double*, const int&)>( amplitude , "AMP" ) << std::endl; @@ -211,7 +195,7 @@ void CoherentSum::generateSourceCode(const std::string& fname, const double& nor stream << "extern \"C\" const char* matrix_elements(int n) {\n"; for ( size_t i = 0; i < m_matrixElements.size(); i++ ) { - stream << " if(n ==" << i << ") return \"" << m_matrixElements.at(i).amp.progName() << "\" ;\n"; + stream << " if(n ==" << i << ") return \"" << m_matrixElements.at(i).progName() << "\" ;\n"; } stream << " return 0;\n}\n"; stream << "extern \"C\" void FCN_all(double* out, double* events, unsigned int size, int parity, double* amps){\n"; @@ -233,7 +217,7 @@ void CoherentSum::generateSourceCode(const std::string& fname, const double& nor int parity = p.decayTree.finalStateParity(); if ( parity == -1 ) stream << "double(parity) * "; stream << "std::complex(amps[" << i * 2 << "],amps[" << i * 2 + 1 << "]) * "; - stream << programatic_name( p.amp.name() )<< "_wParams( E )"; + stream << programatic_name( p.name() )<< "_wParams( E )"; stream << ( i == size() - 1 ? ";" : " +" ) << "\n"; } stream << " out[i] = std::norm(amplitude) / " << normalisation << ";\n }\n}\n"; @@ -255,19 +239,18 @@ void CoherentSum::generateSourceCode(const std::string& fname, const double& nor complex_t CoherentSum::getValNoCache( const Event& evt ) const { return utils::get<0>( complex_v(std::accumulate( m_matrixElements.begin(), - m_matrixElements.end(), - complex_v(0,0), - [&evt]( const auto& a, const auto& b ){ return a + b.coefficient * b(evt);} )) ); + m_matrixElements.end(), + complex_v(0,0), + [&evt]( const auto& a, const auto& b ){ return a + b.coefficient * b(evt);} )) ); } void CoherentSum::reset( bool resetEvents ) { m_prepareCalls = 0; m_lastPrint = 0; - for ( auto& mE : m_matrixElements ) mE.addressData = 999; if ( resetEvents ){ m_events = nullptr; - m_integrator = Integrator_type(); + m_integrator = Integrator(); } } @@ -275,7 +258,9 @@ void CoherentSum::setEvents( EventList_type& list ) { if ( m_verbosity ) INFO( "Setting event list with:" << list.size() << " events for " << this ); reset(); + if( m_ownEvents && m_events != nullptr ) delete m_events; m_events = &list; + m_cache = Store( m_events->size(), m_matrixElements ); } @@ -283,7 +268,7 @@ void CoherentSum::setMC( EventList_type& sim ) { if ( m_verbosity ) INFO( "Setting norm. event list with:" << sim.size() << " events for " << this ); reset(); - m_integrator = Integrator_type( &sim ); + m_integrator = Integrator( &sim, m_matrixElements ); } real_t CoherentSum::norm() const @@ -319,8 +304,8 @@ void CoherentSum::transferParameters() void CoherentSum::printVal(const Event& evt) { for ( auto& mE : m_matrixElements ) { - unsigned int address = mE.addressData; - std::cout << mE.decayTree.decayDescriptor() << " = " << mE.coefficient << " x " << m_events->cache( evt.index(), address ) + unsigned int address = std::distance( &mE , &m_matrixElements[0] ); + std::cout << mE.decayTree.decayDescriptor() << " = " << mE.coefficient << " x " << m_cache( evt.index() / utils::size::value, address ) << " address = " << address << " " << mE( evt ) << std::endl; if( mE.coupling.size() != 1 ){ std::cout << "CouplingConstants: " << std::endl; @@ -333,57 +318,50 @@ void CoherentSum::printVal(const Event& evt) complex_t CoherentSum::getVal( const Event& evt ) const { complex_v value( 0., 0. ); - for ( const auto& mE : m_matrixElements ) { - value = value + mE.coefficient * m_events->cache( evt.index(), mE.addressData ); + for (unsigned int i = 0 ; i != m_matrixElements.size(); ++i ) { + value = value + m_matrixElements[i].coefficient * m_cache(evt.index() / utils::size::value, i ); } - #if ENABLE_AVX2 - return value.at(evt.index() % float_v::size); - #else +#if ENABLE_AVX2 + return value.at(evt.index() % utils::size::value ); +#else return value; - #endif +#endif } -#if ENABLE_AVX2 float_v CoherentSum::operator()( const float_v* /*evt*/, const unsigned block ) const { complex_v value( 0., 0. ); - for ( const auto& mE : m_matrixElements ) { - value = value + mE.coefficient * m_events->cache()[ block * m_events->cacheSize() + mE.addressData ]; + for ( const auto& mE : m_matrixElements ) + { + unsigned address = &mE - &m_matrixElements[0]; + value = value + mE.coefficient * m_cache(block, address); } - return (m_weight/m_norm ) * AVX2::norm( value ); + return (m_weight/m_norm ) * utils::norm(value); } -#endif - - -std::function CoherentSum::evaluator(const EventList_type* events) const +std::function CoherentSum::evaluator(const EventList_type* ievents) const { - if( events != nullptr && events != m_integrator.events() ) - ERROR("Evaluator only working on the integration sample, fix me!"); - std::vector address_mapping( size() ); - for( const auto& me : m_matrixElements ) address_mapping[me.addressData] = m_integrator.getCacheIndex( me.amp ); - std::vector values( events->size() ); + auto events = ievents == nullptr ? m_integrator.events() : ievents; + Store store( events->store(), m_matrixElements); + std::vector values( events->aligned_size() ); #ifdef _OPENMP #pragma omp parallel for #endif - for( unsigned int i = 0 ; i != events->size(); ++i ) + for( unsigned int block = 0 ; block != events->nBlocks(); ++block ) { - complex_t amp = 0; - for( unsigned j = 0 ; j != address_mapping.size(); ++j ) amp += m_matrixElements[j].coefficient * this->m_integrator.get(address_mapping[j], i); - values[i] = m_weight * std::norm(amp) / m_norm; + complex_v amp(0.,0.); + for( unsigned j = 0 ; j != m_matrixElements.size(); ++j ) + amp = amp + m_matrixElements[j].coefficient * store(block, j); + utils::store( values.data() + block * utils::size::value, (m_weight/m_norm) * utils::norm(amp) ); } return arrayToFunctor(values); } -KeyedView CoherentSum::componentEvaluator(const EventList_type* events) const +KeyedView CoherentSum::componentEvaluator(const EventList_type* ievents) const { - if( events != nullptr && events != m_integrator.events() ) - ERROR("Evaluator only working on the integration sample, fix me!"); - - KeyedView rt(*events, m_matrixElements.size() ); - std::vector address_mapping(m_matrixElements.size()); - for( unsigned i = 0; i != m_matrixElements.size(); ++i ) address_mapping[i] = m_integrator.getCacheIndex( m_matrixElements[i].amp ); + auto events = ievents == nullptr ? m_integrator.events() : ievents; + KeyedView rt(*events, m_matrixElements.size() ); for( unsigned i = 0 ; i != m_matrixElements.size(); ++i ) { auto& me = m_matrixElements[i]; @@ -395,12 +373,11 @@ KeyedView CoherentSum::componentEvaluator(c { complex_t total = 0; for( unsigned j = 0 ; j != m_matrixElements.size(); ++j ){ - total += this->m_integrator.get( address_mapping[i], evt ) * m_matrixElements[i].coefficient - * std::conj( this->m_integrator.get( address_mapping[j], evt ) * m_matrixElements[j].coefficient ); + total += this->m_integrator.get(i, evt) * m_matrixElements[i].coefficient + * std::conj( this->m_integrator.get(j, evt) * m_matrixElements[j].coefficient ); } rt(events->at(evt), i) = m_weight * std::real( total ) / m_norm; } } return rt; } - diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index fea41d84a69..acf12e97540 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -102,7 +102,7 @@ void CompiledExpressionBase::to_stream( std::ostream& stream ) const else { auto as_tensor = cast(m_obj).tensor(); for(unsigned j=0; j != as_tensor.size(); ++j ) - stream << "r["<("IncludePythonBindings", false) == true && returnTypename().find("complex") != std::string::npos ){ -// stream << "#pragma clang diagnostic pop\n\n"; stream << "extern \"C\" void " << progName() << "_c" << "(double *real, double *imag, " << fcnSignature() << "){\n"; stream << " auto val = " << progName() << "(" << args() << ") ;\n"; stream << " *real = val.real();\n"; @@ -161,10 +160,10 @@ void CompiledExpressionBase::addDebug( std::ostream& stream ) const } } -std::string CompiledExpressionBase::fcnSignature(const std::vector& argList, bool rto=false) +std::string CompiledExpressionBase::fcnSignature(const std::vector& argList, bool rto, bool includeStagger) { unsigned counter=0; auto fcn = [counter](const auto& str) mutable {return str + " x"+std::to_string(counter++); }; - if( rto ) return argList[0] + " r, " + vectorToString( argList.begin()+1, argList.end(), ", ", fcn ); + if( rto ) return argList[0] + " r, " + argList[1] + " s, " + vectorToString( argList.begin()+2, argList.end(), ", ", fcn ); return vectorToString( argList.begin(), argList.end(), ", ", fcn); } diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index edfb02d59e6..b018506382e 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -53,7 +53,8 @@ void CompilerWrapper::generateSource( const CompiledExpressionBase& expression, { std::ofstream output( filename ); for ( auto& include : m_includes ) output << "#include <" << include << ">\n"; - if( expression.fcnSignature().find("AVX2") != std::string::npos ) output << "#include \"AmpGen/simd/avx2_types.h\"\n" ; + if( expression.fcnSignature().find("AVX2d") != std::string::npos ) output << "#include \"AmpGen/simd/avx2d_types.h\"\n; using namespace AmpGen::AVX2d;\n" ; + else if( expression.fcnSignature().find("AVX2") != std::string::npos ) output << "#include \"AmpGen/simd/avx2_types.h\"\n; using namespace AmpGen::AVX2;\n;" ; output << expression << std::endl; output.close(); } diff --git a/src/ErrorPropagator.cpp b/src/ErrorPropagator.cpp index 44e1b72ae07..815b50e577a 100644 --- a/src/ErrorPropagator.cpp +++ b/src/ErrorPropagator.cpp @@ -106,7 +106,7 @@ double LinearErrorPropagator::getError( const std::function& fcn ) unsigned int N = m_cov.GetNrows(); TVectorD errorVec( N ); for ( unsigned int i = 0; i < N; ++i ) { - DEBUG( "Perturbing parameter: [" << m_parameters[i]->name() << "] " << startingValue << " by " + DEBUG( "Perturbing parameter: [" << m_parameters[i]->name() << "] " << m_parameters[i]->mean() << " by " << sqrt( m_cov( i, i ) ) << " " << m_parameters[i] ); errorVec(i) = derivative(fcn,i); fcn(); diff --git a/src/EventList.cpp b/src/EventList.cpp index 1ec87d4d377..4ab59d90009 100644 --- a/src/EventList.cpp +++ b/src/EventList.cpp @@ -185,39 +185,11 @@ TH2D* EventList::makeProjection( const Projection2D& projection, const ArgumentP return plot; } -void EventList::printCacheInfo( const unsigned int& nEvt ) -{ - for ( auto& ind : m_pdfIndex ) { - INFO( "Cache[" << ind.second << "] = " << ind.first << " = " << cache(nEvt, ind.second ) ); - } -} - -size_t EventList::getCacheIndex( const CompiledExpressionBase& PDF ) const -{ - auto pdfIndex = m_pdfIndex.find( FNV1a_hash( PDF.name() ) ); - if ( pdfIndex != m_pdfIndex.end() ) - return pdfIndex->second; - else - ERROR( "FATAL: PDF Index for " << PDF.name() << " not found" ); - return 999; -} - -size_t EventList::getCacheIndex( const CompiledExpressionBase& PDF, bool& isRegistered ) const -{ - auto pdfIndex = m_pdfIndex.find( FNV1a_hash( PDF.name() ) ); - if ( pdfIndex != m_pdfIndex.end() ) { - isRegistered = true; - return pdfIndex->second; - } - isRegistered = false; - return 999; -} - -void EventList::resetCache() -{ - m_pdfIndex.clear(); - m_cache.clear(); -} +// void EventList::resetCache() +// { +// m_index.clear(); +// //m_cache.clear(); +// } double EventList::integral() const { @@ -226,8 +198,6 @@ double EventList::integral() const void EventList::add( const EventList& evts ) { - resetCache(); - WARNING( "Adding event lists invalidates cache state" ); for ( auto& evt : evts ) m_data.push_back( evt ); } @@ -242,9 +212,9 @@ void EventList::erase(const std::vector::iterator& begin, m_data.erase( begin, end ); } -void EventList::reserveCache(const size_t& size) -{ - if ( size * m_data.size() >= m_cache.size() ) - m_cache.reserve( m_data.size() * m_cache.size() ); -} +//void EventList::reserveCache(const size_t& size) +//{ +// if ( size * m_data.size() >= m_cache.size() ) +// m_cache.reserve( m_data.size() * m_cache.size() ); +//} diff --git a/src/EventListSIMD.cpp b/src/EventListSIMD.cpp index bf7b0ff4864..0492917bf82 100644 --- a/src/EventListSIMD.cpp +++ b/src/EventListSIMD.cpp @@ -33,7 +33,7 @@ #include "AmpGen/simd/utils.h" using namespace AmpGen; -EventListSIMD::EventListSIMD( const EventType& type ) : m_eventType( type ), m_eventSize( m_eventType.eventSize() ) {} +EventListSIMD::EventListSIMD( const EventType& type ) : m_eventType( type ) {} void EventListSIMD::loadFromFile( const std::string& fname, const ArgumentPack& args ) { @@ -104,21 +104,19 @@ void EventListSIMD::loadFromTree( TTree* tree, const ArgumentPack& args ) for( int i = 0 ; i < evtList->GetN(); ++i ) entryList.push_back( evtList->GetEntry(i) ); } bool hasEventList = entryList.size() != 0; - m_nEvents = hasEventList ? entryList.size() : tree->GetEntries(); - auto aligned_size = utils::aligned_size(m_nEvents); + size_t nEvents = hasEventList ? entryList.size() : tree->GetEntries(); std::array buffer; - m_nBlocks = aligned_size / float_v::size; - m_data.resize( m_nBlocks * m_eventSize ); - m_weights.resize( m_nBlocks ); - m_genPDF.resize( m_nBlocks ); + m_data = Store(nEvents, m_eventType.eventSize() ); + m_weights.resize( m_data.nBlocks() ); + m_genPDF.resize( m_data.nBlocks() ); auto symmetriser = m_eventType.symmetriser(); - for ( unsigned int block = 0; block < m_nBlocks; ++block ) + for ( unsigned int block = 0; block < m_data.nBlocks(); ++block ) { for( unsigned k = 0 ; k != float_v::size; ++k ) { auto evt = k + block * float_v::size; - if(evt >= m_nEvents ) break; + if(evt >= m_data.size() ) break; tr.getEntry( hasEventList ? entryList[evt] : evt ); if( applySym ) symmetriser( temp ); buffer[k] = temp; @@ -132,18 +130,15 @@ void EventListSIMD::loadFromTree( TTree* tree, const ArgumentPack& args ) EventListSIMD::EventListSIMD( const EventList& other ) : EventListSIMD( other.eventType() ) { - unsigned aligned_size = utils::aligned_size(other.size()); - m_nBlocks = aligned_size / float_v::size; - m_nEvents = other.size(); - m_data.resize( m_nBlocks * m_eventSize ) ; - m_weights.resize( m_nBlocks ); - m_genPDF.resize ( m_nBlocks ); - for( unsigned evt = 0 ; evt != m_nBlocks; evt ++ ) + m_data = Store(other.size(), m_eventType.eventSize() ); + m_weights.resize( m_data.nBlocks() ); + m_genPDF.resize ( m_data.nBlocks() ); + for( unsigned block = 0 ; block != m_data.nBlocks(); block++ ) { - for( unsigned j = 0 ; j != m_eventSize; ++j ) - m_data[m_eventSize * evt + j] = utils::gather(other, [j](auto& event){ return event[j]; } , evt * float_v::size ); - m_weights[evt] = utils::gather(other, [](auto& event){ return event.weight(); }, evt * float_v::size, 0); - m_genPDF [evt] = utils::gather(other, [](auto& event){ return event.genPdf(); }, evt * float_v::size, 1 ); + for( unsigned j = 0 ; j != m_data.nFields(); ++j ) + m_data(block, j ) = utils::gather(other, [j](auto& event){ return event[j]; } , block * float_v::size ); + m_weights[block] = utils::gather(other, [](auto& event){ return event.weight(); }, block * float_v::size, 0); + m_genPDF [block] = utils::gather(other, [](auto& event){ return event.genPdf(); }, block * float_v::size, 1 ); } } @@ -215,48 +210,10 @@ TH2D* EventListSIMD::makeProjection( const Projection2D& projection, const Argum return plot; } -size_t EventListSIMD::getCacheIndex( const CompiledExpressionBase& PDF ) const -{ - auto pdfIndex = m_pdfIndex.find( FNV1a_hash( PDF.name() ) ); - if ( pdfIndex != m_pdfIndex.end() ) - return pdfIndex->second; - else - ERROR( "FATAL: PDF Index for " << PDF.name() << " not found" ); - return 999; -} - -size_t EventListSIMD::getCacheIndex( const CompiledExpressionBase& PDF, bool& isRegistered ) const -{ - auto pdfIndex = m_pdfIndex.find( FNV1a_hash( PDF.name() ) ); - if ( pdfIndex != m_pdfIndex.end() ) { - isRegistered = true; - return pdfIndex->second; - } - isRegistered = false; - return 999; -} - -void EventListSIMD::resetCache() -{ - m_pdfIndex.clear(); - m_cache.clear(); -} void EventListSIMD::clear() { m_data.clear(); - m_cache.clear(); -} - -void EventListSIMD::reserveCache(const unsigned& newSize) -{ - m_cache.reserve( newSize * nBlocks() ); -} - -void EventListSIMD::resizeCache(const unsigned& newSize ) -{ - WARNING("Will only reserve, because i don't want to keep track anymore ... "); - reserveCache( newSize ); } const Event EventListSIMD::operator[]( const size_t& pos ) const @@ -264,9 +221,9 @@ const Event EventListSIMD::operator[]( const size_t& pos ) const unsigned nEvents = size(); unsigned p = pos / float_v::size; unsigned q = pos % float_v::size; - Event tempEvent( m_eventSize ); - for( unsigned i = 0 ; i != m_eventSize; ++i ) - tempEvent[i] = m_data[p * m_eventSize + i ].at(q); + Event tempEvent( eventSize() ); + for( unsigned i = 0 ; i != tempEvent.size(); ++i ) + tempEvent[i] = m_data(p, i).at(q); tempEvent.setWeight( m_weights[p].at(q) ); tempEvent.setGenPdf( m_genPDF[p].at(q) ); tempEvent.setIndex( pos ); @@ -280,13 +237,13 @@ std::array EventListSIMD::scatter( unsigned pos ) auto vw = m_weights[p].to_array(); auto vg = m_genPDF[p].to_array(); for( unsigned evt = 0 ; evt != float_v::size; ++evt ){ - rt[evt] = Event( m_eventSize ); + rt[evt] = Event( m_data.nFields() ); rt[evt].setWeight(vw[evt]); rt[evt].setGenPdf(vg[evt]); rt[evt].setIndex(evt + pos); } - for( unsigned field = 0 ; field != m_eventSize; ++field){ - auto v = m_data[p * m_eventSize +field].to_array(); + for( unsigned field = 0 ; field != m_data.nFields(); ++field){ + auto v = m_data(p, field).to_array(); for( unsigned evt = 0; evt != float_v::size; ++evt ) rt[evt][field] = v[evt]; } return rt; @@ -294,8 +251,8 @@ std::array EventListSIMD::scatter( unsigned pos ) void EventListSIMD::gather( const std::array& data, unsigned pos ) { - for( unsigned field = 0 ; field != m_eventSize; ++field ) - m_data[pos*m_eventSize +field] = utils::gather(data, [field](auto& event){ return event[field]; } ); + for( unsigned field = 0; field != m_data.nFields(); ++field ) + m_data(pos, field) = utils::gather(data, [field](auto& event){ return event[field]; } ); m_weights[pos] = utils::gather(data, [](auto& event){ return event.weight() ; } ); m_genPDF[pos] = utils::gather(data, [](auto& event){ return event.genPdf(); } ); } diff --git a/src/Expression.cpp b/src/Expression.cpp index 88551e23f02..058ee0d342a 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -59,12 +59,12 @@ std::string Constant::to_string(const ASTResolver* resolver) const { std::string literalSuffix = ""; if( resolver != nullptr && resolver->enableCuda() ) { - complex_type = "ampgen_cuda::complex_t"; + complex_type = "AmpGen::CUDA::complex_t"; literalSuffix = "f"; } if( resolver != nullptr && resolver->enableAVX() ) { - complex_type = "AmpGen::AVX2::complex_t"; + complex_type = "AmpGen::AVX2d::complex_t"; literalSuffix = "f"; } return std::imag(m_value) == 0 ? "(" + rounded_string(std::real(m_value)) +literalSuffix + ")" : @@ -215,7 +215,7 @@ Ternary::Ternary( const Expression& cond, const Expression& v1, const Expression } std::string Ternary::to_string(const ASTResolver* resolver) const { - return resolver != nullptr && resolver->enableAVX() ? "AmpGen::AVX2::select(" + m_cond.to_string(resolver) + ", " + + return resolver != nullptr && resolver->enableAVX() ? "AmpGen::AVX2d::select(" + m_cond.to_string(resolver) + ", " + m_v1.to_string(resolver) + ", " + m_v2.to_string(resolver) +")" : "(" + m_cond.to_string(resolver) + "?" + m_v1.to_string(resolver) + ":" + m_v2.to_string(resolver) + ")"; } diff --git a/src/Integrator.cpp b/src/Integrator.cpp index c1e45cf2d21..531248a016b 100644 --- a/src/Integrator.cpp +++ b/src/Integrator.cpp @@ -36,42 +36,29 @@ void Bilinears::resize( const size_t& r, const size_t& c) void Integrator::integrateBlock() { - real_t re[N] = {0}; - real_t im[N] = {0}; - size_t addr_i[N] = {0}; - size_t addr_j[N] = {0}; - for( size_t roll = 0 ; roll < N; ++roll ) - { - addr_i[roll] = m_integrals[roll].i; - addr_j[roll] = m_integrals[roll].j; - } + #pragma omp parallel for for ( size_t roll = 0; roll < N; ++roll ) { - complex_t* b1 = m_cache.data() + m_integrals[roll].i * m_events->size(); - complex_t* b2 = m_cache.data() + m_integrals[roll].j * m_events->size(); - #pragma omp parallel for reduction(+: re, im) - for ( size_t i = 0; i < m_events->size(); ++i ) { - auto c = b1[i] * std::conj(b2[i]); - re[roll] += m_weight[i] * std::real(c); - im[roll] += m_weight[i] * std::imag(c); + float_v re( 0.f ); + float_v im( 0.f ); + auto b1 = m_cache.data() + m_integrals[roll].i * m_cache.nBlocks(); + auto b2 = m_cache.data() + m_integrals[roll].j * m_cache.nBlocks(); + for ( size_t i = 0; i < m_cache.nBlocks(); ++i ) { + auto c = b1[i] * conj(b2[i]); + #if ENABLE_AVX2 + re = fmadd(re, m_weight[i], real(c) ); + im = fmadd(im, m_weight[i], imag(c) ); + #else + re = re + m_weight[i] * real(c); + im = im + m_weight[i] * imag(c); + #endif } + m_integrals[roll].transfer( utils::sum_elements( complex_v(re, im) ) / m_norm ); } - for ( size_t j = 0; j < m_counter; ++j ) m_integrals[j].transfer( complex_t( re[j], im[j] ) / m_norm ); m_counter = 0; } -Integrator::Integrator( const EventList* events ) : m_events( events ) -{ - if( m_events == nullptr ) return; - m_weight.resize( m_events->size() ); - for( size_t i = 0 ; i < m_events->size(); ++i ) - { - m_weight[i] = m_events->at(i).weight() / m_events->at(i).genPdf(); - m_norm += m_weight[i]; - } -} - bool Integrator::isReady() const { return m_events != nullptr; } -const EventList* Integrator::events() const { return m_events; } + void Integrator::queueIntegral(const size_t& c1, const size_t& c2, const size_t& i, @@ -81,32 +68,36 @@ void Integrator::queueIntegral(const size_t& c1, { if( !out->workToDo(i,j) ) return; if( sim ) - addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ - out->set(i,j,val); - if( i != j ) out->set(j,i, std::conj(val) ); } ); + addIntegralKeyed( c1, c2, [out,i,j]( const complex_t& val ){ out->set(i,j,val); if( i != j ) out->set(j,i, std::conj(val) ); } ); else - addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ out->set(i,j,val); } ); + addIntegralKeyed( c1, c2, [out,i,j]( const complex_t& val ){ out->set(i,j,val); } ); } + void Integrator::addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ) { - m_integrals[m_counter++] = Integral(c1,c2,tFunc); + m_integrals[m_counter++] = Integral(c1,c2,tFunc); if ( m_counter == N ) integrateBlock(); } + void Integrator::queueIntegral(const size_t& i, const size_t& j, complex_t* result) { - addIntegralKeyed(i, j, [result](arg& val){ *result = val ; } ); + addIntegralKeyed(i, j, [result](const complex_t& val){ *result = val ; } ); } + void Integrator::flush() { if ( m_counter == 0 ) return; integrateBlock(); } -void Integrator::setBuffer( complex_t* pos, const complex_t& value, const size_t& size ) + +#if ENABLE_AVX2 +template <> complex_t Integrator::get( const unsigned& index, const unsigned& evt ) const { - *pos = value; + return utils::at( m_cache( evt/utils::size::value, index), evt % utils::size::value ); } +#endif -void Integrator::setBuffer( complex_t* pos, const std::vector& value, const size_t& size) +template <> complex_v Integrator::get( const unsigned& index, const unsigned& evt ) const { - memcpy( pos, &(value[0]), size * sizeof(complex_t) ); + return m_cache(evt, index); } diff --git a/src/IntegratorSIMD.cpp b/src/IntegratorSIMD.cpp deleted file mode 100644 index 375d84a3181..00000000000 --- a/src/IntegratorSIMD.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "AmpGen/IntegratorSIMD.h" -#include "AmpGen/simd/utils.h" - -using namespace AmpGen; -using namespace AmpGen::AVX2; - -void IntegratorSIMD::integrateBlock() -{ - #pragma omp parallel for - for ( size_t roll = 0; roll < N; ++roll ) { - float_v re( _mm256_set1_ps(0.f) ); - float_v im( _mm256_set1_ps(0.f) ); - auto b1 = m_cache.data() + m_integrals[roll].i * m_events->size(); - auto b2 = m_cache.data() + m_integrals[roll].j * m_events->size(); - for ( size_t i = 0; i < m_events->nBlocks(); ++i ) { - auto c = b1[i] * conj(b2[i]); - re = _mm256_fmadd_ps(re, m_weight[i], real(c) ); - im = _mm256_fmadd_ps(im, m_weight[i], imag(c) ); - } - m_integrals[roll].transfer( complex_t( utils::sum_elements(float_v(re)), - utils::sum_elements(float_v(im)) ) / m_norm ); - } - m_counter = 0; -} - -IntegratorSIMD::IntegratorSIMD( const EventListSIMD* events ) : m_events( events ) -{ - if( m_events == nullptr ) return; - m_weight.resize( m_events->nBlocks() ); - float_v norm_acc = 0.; - for( size_t i = 0 ; i < m_events->nBlocks(); ++i ) - { - m_weight[i] = m_events->weight(i) / m_events->genPDF(i); - norm_acc = norm_acc + m_weight[i]; - } - m_norm = utils::sum_elements(norm_acc); -} - -bool IntegratorSIMD::isReady() const { return m_events != nullptr; } - -void IntegratorSIMD::queueIntegral(const size_t& c1, - const size_t& c2, - const size_t& i, - const size_t& j, - Bilinears* out, - const bool& sim) -{ - if( !out->workToDo(i,j) ) return; - if( sim ) - addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ - out->set(i,j,val); - if( i != j ) out->set(j,i, std::conj(val) ); } ); - else - addIntegralKeyed( c1, c2, [out,i,j]( arg& val ){ out->set(i,j,val); } ); -} -void IntegratorSIMD::addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ) -{ - m_integrals[m_counter++] = Integral(c1,c2,tFunc); - if ( m_counter == N ) integrateBlock(); -} -void IntegratorSIMD::queueIntegral(const size_t& i, const size_t& j, complex_t* result) -{ - addIntegralKeyed(i, j, [result](arg& val){ *result = val ; } ); -} -void IntegratorSIMD::flush() -{ - if ( m_counter == 0 ) return; - integrateBlock(); -} diff --git a/src/Lineshapes/CoupledChannel.cpp b/src/Lineshapes/CoupledChannel.cpp index 8f8d149e159..a6715dd9212 100644 --- a/src/Lineshapes/CoupledChannel.cpp +++ b/src/Lineshapes/CoupledChannel.cpp @@ -13,6 +13,8 @@ using namespace AmpGen; using namespace AmpGen::fcn; using namespace std::complex_literals; +// ENABLE_DEBUG( Lineshape::CoupledChannel ); + Expression H(const Expression& x, const Expression& y, const Expression& z ) @@ -117,7 +119,7 @@ DEFINE_LINESHAPE( CoupledChannel ) ADD_DEBUG( s , dbexpressions ); for( size_t i = 0 ; i < channels.size(); i+=2 ){ Particle p( channels[i] ); - INFO( "Adding channel ... " << p.uniqueString() << " coupling = " << NamedParameter( channels[i+1] ) ); + DEBUG( "Adding channel ... " << p.uniqueString() << " coupling = " << NamedParameter( channels[i+1] ) ); Expression coupling = Parameter(channels[i+1], 0); totalWidth = totalWidth + coupling * phaseSpace(s , p, p.L()); totalWidthAtPole = totalWidthAtPole + coupling * phaseSpace(mass*mass, p, p.L()); diff --git a/src/Minimiser.cpp b/src/Minimiser.cpp index 29cd3312e7b..3c7f326fad8 100644 --- a/src/Minimiser.cpp +++ b/src/Minimiser.cpp @@ -29,9 +29,7 @@ double Minimiser::operator()( const double* xx ) m_parSet->at( m_mapping[i] )->setCurrentFitVal( xx[i] ); } double LL = m_theFunction() ; - for ( auto& extendTerm : m_extendedTerms ) { - LL -= 2 * extendTerm->getVal(); - } + for ( auto& extendTerm : m_extendedTerms ) LL -= 2 * extendTerm->getVal(); return LL - m_ll_zero; } @@ -59,7 +57,7 @@ void Minimiser::prepare() { std::string algorithm = NamedParameter( "Minimiser::Algorithm", "Hesse"); size_t maxCalls = NamedParameter( "Minimiser::MaxCalls" , 100000); - double tolerance = NamedParameter( "Minimiser::Tolerance" , 2.0); + double tolerance = NamedParameter( "Minimiser::Tolerance" , 1.0); m_printLevel = NamedParameter( "Minimiser::PrintLevel", 4); m_normalise = NamedParameter( "Minimiser::Normalise",false); if ( m_minimiser != nullptr ) delete m_minimiser; @@ -68,6 +66,8 @@ void Minimiser::prepare() m_minimiser->SetMaxFunctionCalls( maxCalls ); m_minimiser->SetMaxIterations( 100000 ); m_minimiser->SetTolerance( tolerance ); +// m_minimiser->SetStrategy( 3 ); + // m_minimiser->SetPrecision(std::numeric_limits::epsilon()); m_minimiser->SetPrintLevel( m_printLevel ); m_mapping.clear(); m_covMatrix.clear(); diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 34083588200..64ff4b5ebec 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -29,12 +29,20 @@ #include "AmpGen/DiracMatrices.h" #include "AmpGen/Simplify.h" #include "AmpGen/enum.h" +#include "AmpGen/simd/utils.h" using namespace AmpGen; using namespace std::complex_literals; namespace AmpGen { make_enum(spaceType, spin, flavour) } +std::vector convertProxies(const std::vector& proxyVector, const std::function& transform) +{ + std::vector rt; + std::transform(proxyVector.begin(), proxyVector.end(), std::back_inserter(rt), transform ); + return rt; +} + PolarisedSum::PolarisedSum(const EventType& type, MinuitParameterSet& mps, const std::vector& pVector) @@ -63,9 +71,7 @@ PolarisedSum::PolarisedSum(const EventType& type, { tp.enqueue( [i, &protoAmps, &polStates, this]{ Tensor thisExpression( Tensor::dim(polStates.size()) ); - auto& p = protoAmps[i].first; - auto& coupling = protoAmps[i].second; - //auto& [p,coupling] = protoAmps.at(i); + auto& [p, coupling] = protoAmps[i]; DebugSymbols syms; for(unsigned j = 0; j != polStates.size(); ++j){ p.setPolarisationState( polStates[j] ); @@ -74,11 +80,11 @@ PolarisedSum::PolarisedSum(const EventType& type, m_matrixElements[i] = TransitionMatrix( p, coupling, - CompiledExpression( + CompiledExpression( TensorExpression(thisExpression), p.decayDescriptor(), this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,this->m_mps ) ); - CompilerWrapper().compile( m_matrixElements[i].amp ); + CompilerWrapper().compile( m_matrixElements[i] ); }); } } @@ -100,11 +106,11 @@ PolarisedSum::PolarisedSum(const EventType& type, m_matrixElements[i] = TransitionMatrix( tm.first, tm.second, - CompiledExpression( + CompiledExpression( TensorExpression(thisExpression), tm.first.decayDescriptor(), this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,this->m_mps ) ); - CompilerWrapper().compile( m_matrixElements[i].amp ); + CompilerWrapper().compile( m_matrixElements[i] ); }); } } @@ -116,6 +122,12 @@ PolarisedSum::PolarisedSum(const EventType& type, else if( m_dim.first == 3 ) m_pVector = {p("Px"), p("Py"), p("Pz"), p("Tyy"), p("Tzz"), p("Txy"), p("Txz"), p("Tyz")}; } for(size_t i=0; i < m_dim.second * m_dim.first * m_dim.first; ++i) m_norms.emplace_back( m_matrixElements.size(), m_matrixElements.size() ); + + DebugSymbols db; + auto prob = probExpression(transitionMatrix(), convertProxies(m_pVector,[](auto& p){ return Parameter(p->name());} ), m_debug ? &db : nullptr); + m_probExpression = CompiledExpression(prob, "prob_unnormalised", {}, db, m_mps); + CompilerWrapper().compile(m_probExpression); + m_probExpression.prepare(); } std::vector PolarisedSum::polarisations( const std::string& name ) const @@ -172,12 +184,6 @@ std::vector densityMatrix(const unsigned& dim, const std::vector convertProxies(const std::vector& proxyVector, const std::function& transform) -{ - std::vector rt; - std::transform(proxyVector.begin(), proxyVector.end(), std::back_inserter(rt), transform ); - return rt; -} std::vector> PolarisedSum::matrixElements() const { @@ -188,52 +194,44 @@ void PolarisedSum::prepare() { DEBUG( "Preparing: " << m_prefix << " " << m_events << " ready = " << m_integrator.isReady() ); transferParameters(); - size_t nChanges = 0; ProfileClock tEval; size_t size_of = size() / m_matrixElements.size(); - if( m_events != nullptr ) m_events->reserveCache( size() ); - if( m_integrator.isReady() ) m_integrator.allocate(m_matrixElements, size() ); for(auto& t : m_matrixElements){ - if( m_nCalls != 0 && !t.amp.hasExternalsChanged() ) continue; - m_events->updateCache(t.amp, t.addressData); - m_integrator.prepareExpression(t.amp); - t.amp.resetExternals(); + if( m_nCalls != 0 && !t.hasExternalsChanged() ) continue; + if( m_events != nullptr ) m_cache.update(m_events->store(), t); + m_integrator.updateCache(t); + t.resetExternals(); t.workToDo = true; - nChanges++; - if( m_nCalls == 0 && m_integrator.isReady() ) m_integIndex.push_back( m_integrator.getCacheIndex( t.amp ) ); } - if( !m_probExpression.isLinked() ) build_probunnormalised(); tEval.stop(); ProfileClock tIntegral; m_rho = densityMatrix(m_dim.first, m_pVector); - if( m_integrator.isReady() ) - { - if(nChanges != 0) calculateNorms(); - complex_t z = 0; - for(size_t i = 0; i < m_matrixElements.size(); ++i){ - for(size_t j = 0; j < m_matrixElements.size(); ++j){ - // z += ((i==j) ? 1. : 2. ) * m_matrixElements[i].coupling()*std::conj(m_matrixElements[j].coupling())*norm(i,j); - z += m_matrixElements[i].coupling()*std::conj(m_matrixElements[j].coupling())* ( i > j ? std::conj(norm(j,i)) : norm(i,j) ); - } - } - m_norm = std::real(z); - if(m_nCalls % 10000 == 0 && m_prefix == "") debug_norm(); - } - + if( m_integrator.isReady() ) updateNorms(); tIntegral.stop(); - if(m_verbosity && nChanges != 0) - INFO("Time to evaluate = " << tEval << " ms; " << "norm = " << tIntegral << " ms; " << "pdfs = " << nChanges); + if( m_verbosity && m_nCalls % 100 == 0 ){ + INFO("Time to evaluate = " << tEval << " ms; " << "norm = " << tIntegral << " ms; "); + } +// debug_norm(); m_nCalls++; for( auto& me : m_matrixElements ) me.workToDo = false; + auto pw = m_weight / m_norm; + #pragma omp parallel for + for( unsigned block = 0 ; block != m_events->nBlocks(); ++block ) + m_pdfCache[block] = pw * m_probExpression(&m_cache(block, 0)); + + DEBUG( "m_pdfCache[0] = " << m_pdfCache[0] << " w/o caching = " << pw * getValNoCache(m_events->at(0)) ); +} + +float_v PolarisedSum::operator()( const float_v*, const unsigned index ) const +{ + return m_pdfCache[index]; } void PolarisedSum::debug_norm() { double norm_slow = 0; - for( auto& evt : *m_integrator.events() ) + for( auto& evt : *m_integrator.events() ) norm_slow += evt.weight() * getValNoCache(evt) / evt.genPdf(); - auto evt = (*m_integrator.events())[0]; - INFO("Event[0]: " << prob_unnormalised(evt) << " " << getValNoCache(evt) ); INFO("Norm : " << std::setprecision(10) << "bilinears=" << m_norm << "; exact=" << norm_slow / m_integrator.norm() @@ -241,19 +239,22 @@ void PolarisedSum::debug_norm() << "; sample=" << m_integrator.norm() ); } -void PolarisedSum::setEvents( EventList& events ) +void PolarisedSum::setEvents( EventList_type& events ) { reset(); + if( m_events != nullptr && m_ownEvents ) delete m_events; m_events = &events; - for( unsigned i = 0; i != m_matrixElements.size(); ++i ) - m_matrixElements[i].addressData = m_events->registerExpression(m_matrixElements[i].amp, m_dim.first * m_dim.second ); + m_cache = Store(m_events->size(), m_matrixElements, m_dim.first * m_dim.second ); + m_pdfCache.resize( m_events->nBlocks() ); } -void PolarisedSum::setMC( EventList& events ) +void PolarisedSum::setMC( EventList_type& events ) { m_nCalls = 0; - m_integrator = Integrator(&events); - + m_integrator = Integrator(&events, m_matrixElements, m_dim.first * m_dim.second ); + m_integIndex.clear(); + for( auto& i : m_matrixElements ) + m_integIndex.push_back( m_integrator.getCacheIndex(i) ); } size_t PolarisedSum::size() const @@ -263,35 +264,27 @@ size_t PolarisedSum::size() const void PolarisedSum::reset( const bool& flag ){ m_nCalls = 0 ; } -void PolarisedSum::build_probunnormalised() -{ - DebugSymbols db; - auto prob = probExpression(transitionMatrix(), convertProxies(m_pVector,[](auto& p){ return Parameter(p->name());} ), m_debug ? &db : nullptr); - m_probExpression = CompiledExpression(prob, "prob_unnormalised", {}, db, m_mps); - CompilerWrapper().compile(m_probExpression); - m_probExpression.prepare(); -} - Tensor PolarisedSum::transitionMatrix() { auto size = m_dim.first * m_dim.second; std::vector expressions(size, 0); + unsigned totalSize = 0 ; for( auto& me : m_matrixElements ){ auto coupling = me.coupling.to_expression() ; - auto cacheIndex = m_events->getCacheIndex(me.amp); + auto cacheIndex = totalSize; for( size_t i = 0 ; i < size ; ++i ){ expressions[i] = expressions[i] + coupling * Parameter( "x1["+std::to_string(cacheIndex+i)+"]",0,true); } + totalSize += size; } Tensor T_matrix(expressions, {m_dim.first, m_dim.second}); T_matrix.st(); return T_matrix; } -real_t PolarisedSum::prob_unnormalised( const Event& evt ) const -{ - return 0; - //return m_probExpression( &m_events->cache(evt.index(), 0) ); +real_t PolarisedSum::operator()(const Event& evt) const +{ + return utils::at( m_pdfCache[ evt.index() / utils::size::value ], evt.index() % utils::size::value ); } double PolarisedSum::norm() const @@ -316,42 +309,36 @@ complex_t PolarisedSum::norm(const size_t& i, const size_t& j, Integrator* integ return total; } -void PolarisedSum::calculateNorms() +void PolarisedSum::updateNorms() { + if(std::any_of(m_matrixElements.begin(),m_matrixElements.end(), [](auto& me){ return me.workToDo; } )){ for( unsigned i = 0 ; i < m_matrixElements.size(); ++i ){ for( unsigned j = i; j < m_matrixElements.size(); ++j ){ if( m_matrixElements[i].workToDo || m_matrixElements[j].workToDo ) norm(i, j, &m_integrator); } } m_integrator.flush(); -} - -double PolarisedSum::prob(const Event& evt) const -{ - return m_weight * prob_unnormalised(evt) / m_norm; + } + complex_t z = 0; + for(size_t i = 0; i < m_matrixElements.size(); ++i){ + for(size_t j = 0; j < m_matrixElements.size(); ++j){ + z += m_matrixElements[i].coupling()*std::conj(m_matrixElements[j].coupling())* ( i > j ? std::conj(norm(j,i)) : norm(i,j) ); + } + } + m_norm = std::real(z); } void PolarisedSum::debug(const Event& evt) { auto tsize = m_dim.first * m_dim.second; - for(const auto& me : m_matrixElements) + for(unsigned j = 0; j != m_matrixElements.size(); ++j) { - std::vector this_cache(0,tsize); - for(unsigned i = 0 ; i != tsize; ++i ) this_cache.emplace_back( m_events->cache(evt.index(), me.addressData+i) ); - INFO( me.decayDescriptor() << " " << vectorToString( this_cache, " ") ); + std::vector this_cache; + for(unsigned i = 0 ; i != tsize; ++i ) this_cache.emplace_back( m_cache(evt.index() / utils::size::value, j*tsize + i) ); + INFO( m_matrixElements[j].decayDescriptor() << " " << vectorToString( this_cache, " ") ); } - INFO("P(x) = " << getValNoCache(evt) ); + INFO("P(x) = " << getValNoCache(evt) << " " << operator()(nullptr, evt.index() / utils::size::value ) ); INFO("Prod = [" << vectorToString(m_pVector , ", ") <<"]"); - if( m_debug ) - { - transferParameters(); - std::vector cache( tsize * m_matrixElements.size() ); - for( unsigned i = 0 ; i != m_matrixElements.size(); ++i ){ - std::memmove( cache.data() + tsize *i, m_matrixElements[i](evt).data(), tsize * sizeof(complex_t) ); - m_matrixElements[i].amp.debug( evt.address() ); - } - m_probExpression.debug( cache.data() ); - } } void PolarisedSum::generateSourceCode(const std::string& fname, const double& normalisation, bool add_mt) @@ -364,13 +351,13 @@ void PolarisedSum::generateSourceCode(const std::string& fname, const double& no std::vector expressions(size); for( auto& p : m_matrixElements ){ auto expr = CompiledExpression(const real_t*, const real_t*)>( - p.amp.expression(), + p.expression(), p.decayDescriptor(), m_eventType.getEventFormat(), DebugSymbols() ,m_mps ) ; expr.prepare(); expr.to_stream( stream ); expr.compileWithParameters( stream ); - Array z( make_cse( Function( programatic_name( p.amp.name()) + "_wParams", {event} ) ), size ); + Array z( make_cse( Function( programatic_name( p.name()) + "_wParams", {event} ) ), size ); INFO( p.decayDescriptor() << " coupling = " << p.coupling() ); for( unsigned int j = 0 ; j < size; ++j ) expressions[j] = expressions[j] + p.coupling() * z[j]; } @@ -449,8 +436,7 @@ std::vector PolarisedSum::fitFractions(const LinearErrorPropagator& for(const auto& p : outputFractions) INFO(p); if( interferenceFractions ) - { - + { auto head_rules = m_rules.rulesForDecay(m_eventType.mother(), m_prefix); FitFractionCalculator iCalc(this, findIndices(m_matrixElements, m_eventType.mother()), recomputeIntegrals); for(size_t i = 0 ; i < head_rules.size(); ++i) @@ -478,83 +464,77 @@ void PolarisedSum::transferParameters() if( m_probExpression.isLinked() ) m_probExpression.prepare(); for(auto& me : m_matrixElements){ me.coefficient = me.coupling(); - me.amp.prepare(); + me.prepare(); } for(auto& p : m_pVector ) p.update(); m_weight.update(); } -real_t PolarisedSum::getValNoCache( const Event& evt ) +real_t PolarisedSum::getValNoCache( const Event& evt ) const { - transferParameters(); auto tsize = m_dim.first * m_dim.second; - std::vector cache( tsize * m_matrixElements.size() ); + std::vector cache( tsize * m_matrixElements.size() ); for( unsigned i = 0 ; i != m_matrixElements.size(); ++i ){ - std::memmove( cache.data() + tsize *i, m_matrixElements[i](evt).data(), tsize * sizeof(complex_t) ); + std::memmove( cache.data() + tsize * i , m_matrixElements[i](evt).data(), tsize * sizeof(complex_v) ); } - return m_probExpression( cache.data() ); + return utils::get<0>(m_probExpression( cache.data() )); } void PolarisedSum::setWeight( MinuitProxy param ){ m_weight = param; } double PolarisedSum::getWeight() const { return m_weight ; } -std::function PolarisedSum::evaluator(const EventList* events) const + +std::function PolarisedSum::evaluator(const EventList_type* ievents) const { - if( events != nullptr && events != m_integrator.events() ) - ERROR("Evaluator only working on the integration sample, fix me!"); - - std::vector address_mapping( size() ); - for( const auto& me : m_matrixElements ){ - for( unsigned i = 0; i != size() / m_matrixElements.size(); ++i ) - address_mapping[me.addressData+i] = m_integrator.getCacheIndex( me.amp ) + i; - } - std::vector values( m_integrator.events()->size() ); - std::vector buffer(address_mapping.size()); + auto events = ievents == nullptr ? m_integrator.events() : ievents; + Store store( events->size(), m_matrixElements); + for( auto& me : m_matrixElements ) store.update(m_events->store(), me ); + + std::vector values( events->aligned_size() ); #ifdef _OPENMP - #pragma omp parallel for firstprivate(buffer) + #pragma omp parallel for #endif - for( unsigned int i = 0 ; i != m_integrator.events()->size(); ++i ) + for( unsigned int block = 0 ; block != events->nBlocks(); ++block ) { - for( unsigned j = 0 ; j != address_mapping.size(); ++j ) buffer[j] = this->m_integrator.get(address_mapping[j], i); - values[i] = m_weight * m_probExpression(&buffer[0]) / m_norm; + utils::store(values.data() + utils::size::value * block, (m_weight/m_norm) * m_probExpression(&store(block,0)) ); } + for( unsigned int i = 0 ; i != 10; ++i ) + DEBUG(values[i] << " " << getValNoCache( events->at(i) ) * ( m_weight / m_norm ) ); return arrayToFunctor(values); } -KeyedView PolarisedSum::componentEvaluator(const EventList* events) const +KeyedView PolarisedSum::componentEvaluator(const EventList_type* events) const { - if( events != nullptr && events != m_integrator.events() ) - ERROR("Evaluator only working on the integration sample, fix me!"); - KeyedView rt(*events, m_matrixElements.size() ); - std::vector address_mapping(m_matrixElements.size()); - for( unsigned i = 0; i != m_matrixElements.size(); ++i ) - address_mapping[i] = m_integrator.getCacheIndex( m_matrixElements[i].amp ); - - for( unsigned i = 0 ; i != m_matrixElements.size(); ++i ) - { - auto& me = m_matrixElements[i]; - rt.setKey(i, programatic_name( me.decayTree.decayDescriptor() ) ); - #ifdef _OPENMP - #pragma omp parallel for - #endif - for( unsigned evt = 0 ; evt != m_integrator.events()->size(); ++evt ) - { - complex_t total = 0; - for( unsigned j = 0 ; j != m_matrixElements.size(); ++j ){ - for( unsigned x = 0; x != m_norms.size(); ++x ) - { - auto s1 = m_dim.first; - auto s2 = m_dim.second; - auto f = x % s2; - auto psiIndex = (x-f) / s2; - auto m2 = psiIndex % s1; - auto m1 = (psiIndex-m2)/s1; - total += m_rho[psiIndex] * this->m_integrator.get( address_mapping[i] + m1 * s2 + f, evt ) * m_matrixElements[i].coefficient - * std::conj( this->m_integrator.get( address_mapping[j] + m2 * s2 + f, evt ) * m_matrixElements[j].coefficient ); - } - } - rt(events->at(evt), i) = m_weight * std::real( total ) / m_norm; - } - } + KeyedView rt(*events, m_matrixElements.size() ); +// std::vector address_mapping(m_matrixElements.size()); +// for( unsigned i = 0; i != m_matrixElements.size(); ++i ) +// address_mapping[i] = m_integrator.getCacheIndex( m_matrixElements[i].amp ); +// +// for( unsigned i = 0 ; i != m_matrixElements.size(); ++i ) +// { +// auto& me = m_matrixElements[i]; +// rt.setKey(i, programatic_name( me.decayTree.decayDescriptor() ) ); +// #ifdef _OPENMP +// #pragma omp parallel for +// #endif +// for( unsigned evt = 0 ; evt != m_integrator.events()->size(); ++evt ) +// { +// complex_t total = 0; +// for( unsigned j = 0 ; j != m_matrixElements.size(); ++j ){ +// for( unsigned x = 0; x != m_norms.size(); ++x ) +// { +// auto s1 = m_dim.first; +// auto s2 = m_dim.second; +// auto f = x % s2; +// auto psiIndex = (x-f) / s2; +// auto m2 = psiIndex % s1; +// auto m1 = (psiIndex-m2)/s1; +// total += m_rho[psiIndex] * this->m_integrator.get( address_mapping[i] + m1 * s2 + f, evt ) * m_matrixElements[i].coefficient +// * std::conj( this->m_integrator.get( address_mapping[j] + m2 * s2 + f, evt ) * m_matrixElements[j].coefficient ); +// } +// } +// rt(events->at(evt), i) = m_weight * std::real( total ) / m_norm; +// } +// } return rt; } diff --git a/src/Projection.cpp b/src/Projection.cpp index aeeb6901ebc..2afa383fc4f 100644 --- a/src/Projection.cpp +++ b/src/Projection.cpp @@ -76,11 +76,6 @@ template <> TH1D* Projection::projInternal( const EventList& events, const Argum return events.makeProjection(*this, args); } -template <> TH1D* Projection::projInternal( const EventListSIMD& events, const ArgumentPack& args) const -{ - return events.makeProjection(*this, args); -} - template <> std::tuple, THStack*> Projection::projInternal(const EventList& events, const KeyedView& weightFunction, const ArgumentPack& args) const { std::vector hists; @@ -111,6 +106,12 @@ template <> std::tuple, THStack*> Projection::projInternal(co return {hists, stack}; } +#if ENABLE_AVX2 +template <> TH1D* Projection::projInternal( const EventListSIMD& events, const ArgumentPack& args) const +{ + return events.makeProjection(*this, args); +} + template <> std::tuple, THStack*> Projection::projInternal(const EventListSIMD& events, const KeyedView& weightFunction, const ArgumentPack& args) const { std::vector hists; @@ -140,4 +141,4 @@ template <> std::tuple, THStack*> Projection::projInternal(co if( autowrite ) stack->Write(); return {hists, stack}; } - +#endif diff --git a/src/Tensor.cpp b/src/Tensor.cpp index 10c63b83ad9..5195f2299bf 100644 --- a/src/Tensor.cpp +++ b/src/Tensor.cpp @@ -413,9 +413,9 @@ TensorProxy AmpGen::operator*( const TensorProxy& t1, const TensorProxy& t2 ) Tensor value( finalTensorRank ); unsigned nElem = value.nElements(); - DEBUG("Got " << t1_tensor.dims().size() << " x " << t2_tensor.dims().size() << " with " << contractions.size() << " contractions " << nElementsInSum); - DEBUG(t1_tensor.dimString() << " x " << t2_tensor.dimString() << " -> " << value.dimString()); - DEBUG("Contraction matrix = " << "[" << vectorToString(contractionMatrix, ", ") << "]"); + //DEBUG("Got " << t1_tensor.dims().size() << " x " << t2_tensor.dims().size() << " with " << contractions.size() << " contractions " << nElementsInSum); + //DEBUG(t1_tensor.dimString() << " x " << t2_tensor.dimString() << " -> " << value.dimString()); + //DEBUG("Contraction matrix = " << "[" << vectorToString(contractionMatrix, ", ") << "]"); for( unsigned elem = 0; elem < nElem; ++elem ) { auto coords = Tensor::index_to_coordinates( elem, finalTensorRank ); diff --git a/src/UnaryExpression.cpp b/src/UnaryExpression.cpp index 0fb9b4c4994..17fb1ae8882 100644 --- a/src/UnaryExpression.cpp +++ b/src/UnaryExpression.cpp @@ -17,18 +17,18 @@ T rsqrt( const T& arg ){ return 1. / sqrt(arg) ; } DEFINE_UNARY_OPERATOR( Log , log ) DEFINE_UNARY_OPERATOR( Sqrt, sqrt ) DEFINE_UNARY_OPERATOR( Exp , exp ) -DEFINE_UNARY_OPERATOR_NO_RESOLVER( Abs , std::fabs ) DEFINE_UNARY_OPERATOR( Sin , sin ) DEFINE_UNARY_OPERATOR( Cos , cos ) DEFINE_UNARY_OPERATOR( Tan , tan ) DEFINE_UNARY_OPERATOR( ASin, asin ) DEFINE_UNARY_OPERATOR( ACos, acos ) DEFINE_UNARY_OPERATOR( ATan, atan ) -DEFINE_UNARY_OPERATOR( Norm, std::norm ) -DEFINE_UNARY_OPERATOR( Conj, std::conj ) -DEFINE_UNARY_OPERATOR( Real, std::real ) -DEFINE_UNARY_OPERATOR( Imag, std::imag ) +DEFINE_UNARY_OPERATOR_NO_RESOLVER( Norm, std::norm ) +DEFINE_UNARY_OPERATOR_NO_RESOLVER( Real, std::real ) +DEFINE_UNARY_OPERATOR_NO_RESOLVER( Imag, std::imag ) DEFINE_UNARY_OPERATOR_NO_RESOLVER( ISqrt, rsqrt ) +DEFINE_UNARY_OPERATOR_NO_RESOLVER( Conj, std::conj ) +DEFINE_UNARY_OPERATOR_NO_RESOLVER( Abs , std::fabs ) LGamma::LGamma( const Expression& expression) : IUnaryExpression(expression) {} LGamma::operator Expression() const { return Expression( std::make_shared(*this) ) ; } @@ -46,10 +46,39 @@ std::string ISqrt::to_string(const ASTResolver* resolver) const { std::string Abs::to_string( const ASTResolver* resolver ) const { return resolver != nullptr && resolver->enableAVX() ? - "AmpGen::AVX2::abs(" + m_expression.to_string(resolver) +")" : + "abs(" + m_expression.to_string(resolver) +")" : "std::fabs("+m_expression.to_string(resolver) +")"; } +std::string Conj::to_string( const ASTResolver* resolver ) const +{ + return resolver != nullptr && resolver->enableAVX() ? + "conj(" + m_expression.to_string(resolver) +")" : + "std::conj("+m_expression.to_string(resolver) +")"; +} + +std::string Norm::to_string( const ASTResolver* resolver ) const +{ + return resolver != nullptr && resolver->enableAVX() ? + "norm(" + m_expression.to_string(resolver) +")" : + "std::norm("+m_expression.to_string(resolver) +")"; +} + +std::string Real::to_string( const ASTResolver* resolver ) const +{ + return resolver != nullptr && resolver->enableAVX() ? + "real(" + m_expression.to_string(resolver) +")" : + "std::real("+m_expression.to_string(resolver) +")"; +} + +std::string Imag::to_string( const ASTResolver* resolver ) const +{ + return resolver != nullptr && resolver->enableAVX() ? + "imag(" + m_expression.to_string(resolver) +")" : + "std::imag("+m_expression.to_string(resolver) +")"; +} + + Expression Log::d() const { return 1. / arg(); } Expression Sqrt::d() const { return 1. / ( 2 * fcn::sqrt( arg() ) ); } Expression Exp::d() const { return fcn::exp(arg()) ; } diff --git a/src/Utilities.cpp b/src/Utilities.cpp index e0c04a9ce94..e5f135bfe39 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -203,20 +203,16 @@ bool AmpGen::stringMatchesWildcard( const std::string& input, const std::string& { auto pos = wildcard_string.find( wildcard_character ); /// TEST_foobar -> *_foobar if ( wildcard_string.size() == 1 && wildcard_string[0] == wildcard_character ) { - DEBUG( "Returning true" ); return true; } if ( pos == std::string::npos ) { - DEBUG( "Returning " << input << " = " << wildcard_string << " ?" ); return input == wildcard_string; } if ( pos == wildcard_string.size() - 1 ) { - DEBUG( "Returning " << input << " contains " << wildcard_string ); return input.find( wildcard_string.substr( 0, wildcard_string.size() - 1 ) ) == 0; } else { const std::string pattern1 = wildcard_string.substr( 0, pos + 1 ); const std::string pattern2 = wildcard_string.substr( pos + 1 ); - DEBUG( "Matching " << pattern1 << " to " << input ); bool match1 = stringMatchesWildcard( input, pattern1, wildcard_character ); if ( !match1 ) return false; auto pos2 = pattern2.find( wildcard_character ); @@ -285,6 +281,15 @@ void AmpGen::printSplash() #elif defined(__GNUC__) || defined(__GNUG__) std::cout << "gcc " << __GNUC__ << "." << __GNUC_MINOR__ << "." << __GNUC_PATCHLEVEL__; #endif + #if ENABLE_AVX2 + std::cout << " (avx2;"; + #if DOUBLE_PRECISION + std::cout << " double)"; + #else + std::cout << " single)"; + #endif + #endif + std::cout << " " << __DATE__ << " " << __TIME__ << bold_off << "\n\n"; char* AmpGenRoot = getenv("AMPGENROOT"); @@ -336,7 +341,6 @@ std::string AmpGen::expandGlobals( std::string path ) std::string old_path = path; size_t len = end_pos == std::string::npos ? path.length() - pos + 1 : end_pos - pos + 1; path = path.replace( pos, len, global_var ); - DEBUG( old_path << " -> " << path ); } while ( pos != std::string::npos ); return path; From e074da94abe0d188e732912a640349d6505ad77a Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 14 Apr 2020 19:34:40 +0200 Subject: [PATCH 166/250] fixes for travis build --- AmpGen/AmplitudeRules.h | 6 +++++- AmpGen/Event.h | 13 ------------- AmpGen/Store.h | 2 +- src/CoherentSum.cpp | 8 +++++--- src/PolarisedSum.cpp | 4 ++-- 5 files changed, 13 insertions(+), 20 deletions(-) diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index 38823a0dc11..d65df6bf7d0 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -108,8 +108,11 @@ namespace AmpGen #if ENABLE_AVX2 const RT operator()(const Event& event) const { return amp_type::operator()(EventListSIMD::makeEvent(event).data()); } #else - const RT operator()(const Event& event) const { return amp_type::operator()(event.address()); } + const RT operator()(const Event& event) const { return amp_type::operator()(event.address()) ; } #endif + template auto operator()(arg_types... args ) const { return amp_type::operator()(args...) ; } + + const RT operator()(const float_v* t) const { return amp_type::operator()(t) ; } const std::string decayDescriptor() const { return decayTree.decayDescriptor() ; } Particle decayTree; @@ -178,6 +181,7 @@ namespace AmpGen #endif return rt; } + template auto operator()(arg_types... args ) const { return amp_type::operator()(args...) ; } const std::string decayDescriptor() const { return decayTree.decayDescriptor() ; } diff --git a/AmpGen/Event.h b/AmpGen/Event.h index 5c2145301e7..01bc5139f16 100644 --- a/AmpGen/Event.h +++ b/AmpGen/Event.h @@ -26,13 +26,6 @@ namespace AmpGen { void set( const real_t* evt ); void set( const unsigned& i, const real_t& p ) ; void swap( const unsigned int& i , const unsigned int& j ); - // void setCache(const complex_t& value, const unsigned& pos) ; - // template void setCache( const std::array& value, const unsigned& pos ) - // { - // std::memmove( m_cache.data() + pos, value.data(), sizeof(std::array) ); - // } - // void setCache( const std::vector& value, const unsigned& pos ); - // void resizeCache( const unsigned int& new_size ); unsigned size() const { return m_event.size(); } @@ -41,7 +34,6 @@ namespace AmpGen { const real_t* address(const unsigned& ref=0) const { return &(m_event[ref]); } real_t* address(const unsigned& ref=0) { return &(m_event[ref]); } - // unsigned cacheSize() const { return m_cache.size(); } real_t weight() const { return m_weight; } real_t genPdf() const { return m_genPdf; } real_t operator[](const unsigned& i) const { return m_event[i]; } @@ -49,10 +41,6 @@ namespace AmpGen { operator const real_t*() const { return &(m_event[0]); } operator real_t*() { return &(m_event[0]); } - // const complex_t& getCache(const unsigned& pos) const { return m_cache[pos]; } - // const complex_t* getCachePtr(const unsigned& pos=0) const { return &(m_cache[0]) + pos; } - // complex_t* getCachePtr(const unsigned& pos=0) { return &(m_cache[0]) + pos; } - void setWeight( const real_t& weight ){ m_weight = weight ; } void setGenPdf( const real_t& genPdf ){ m_genPdf = genPdf ; } void extendEvent(const real_t& value) { m_event.push_back( value ); } @@ -67,7 +55,6 @@ namespace AmpGen { real_t s( const std::vector& indices ) const ; private: std::vector m_event; - // std::vector m_cache; real_t m_genPdf = {1}; real_t m_weight = {1}; unsigned m_index = {0}; diff --git a/AmpGen/Store.h b/AmpGen/Store.h index 594efb83ff9..ddfb9b0d5da 100644 --- a/AmpGen/Store.h +++ b/AmpGen/Store.h @@ -121,7 +121,7 @@ namespace AmpGen { #pragma omp parallel for #endif for ( size_t evt = 0; evt < events.size(); ++evt ){ - auto tmp = fcn( events[evt].address( ) ); + auto tmp = fcn( events[evt].address() ); store( evt, p0, &tmp, s); } } diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index e74de1ba47a..ad957579520 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -342,12 +342,14 @@ float_v CoherentSum::operator()( const float_v* /*evt*/, const unsigned block ) std::function CoherentSum::evaluator(const EventList_type* ievents) const { auto events = ievents == nullptr ? m_integrator.events() : ievents; - Store store( events->store(), m_matrixElements); + Store store( events->size(), m_matrixElements); + for( auto& me : m_matrixElements ) store.update(m_events->store(), me ); + std::vector values( events->aligned_size() ); #ifdef _OPENMP #pragma omp parallel for #endif - for( unsigned int block = 0 ; block != events->nBlocks(); ++block ) + for( unsigned int block = 0 ; block < events->nBlocks(); ++block ) { complex_v amp(0.,0.); for( unsigned j = 0 ; j != m_matrixElements.size(); ++j ) @@ -369,7 +371,7 @@ KeyedView CoherentSum::componentEvaluator(c #ifdef _OPENMP #pragma omp parallel for #endif - for( unsigned evt = 0 ; evt != events->size(); ++evt ) + for( unsigned evt = 0 ; evt < events->size(); ++evt ) { complex_t total = 0; for( unsigned j = 0 ; j != m_matrixElements.size(); ++j ){ diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 64ff4b5ebec..19bb114c96a 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -216,7 +216,7 @@ void PolarisedSum::prepare() for( auto& me : m_matrixElements ) me.workToDo = false; auto pw = m_weight / m_norm; #pragma omp parallel for - for( unsigned block = 0 ; block != m_events->nBlocks(); ++block ) + for( unsigned block = 0 ; block < m_events->nBlocks(); ++block ) m_pdfCache[block] = pw * m_probExpression(&m_cache(block, 0)); DEBUG( "m_pdfCache[0] = " << m_pdfCache[0] << " w/o caching = " << pw * getValNoCache(m_events->at(0)) ); @@ -494,7 +494,7 @@ std::function PolarisedSum::evaluator(const EventList_type #ifdef _OPENMP #pragma omp parallel for #endif - for( unsigned int block = 0 ; block != events->nBlocks(); ++block ) + for( unsigned int block = 0 ; block < events->nBlocks(); ++block ) { utils::store(values.data() + utils::size::value * block, (m_weight/m_norm) * m_probExpression(&store(block,0)) ); } From a04a7b26fb73999e48f417c5d317f35d3630f741 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 14 Apr 2020 20:58:18 +0200 Subject: [PATCH 167/250] Fix if number of events % simd_size != 0 and Chi2 calculation --- AmpGen/BinDT.h | 2 +- AmpGen/Chi2Estimator.h | 21 ++++++++++++++++----- AmpGen/Store.h | 10 +++++----- AmpGen/SumPDF.h | 2 +- examples/SignalOnlyFitter.cpp | 6 +++--- src/Chi2Estimator.cpp | 6 +++--- src/CoherentSum.cpp | 4 ++-- src/EventListSIMD.cpp | 11 +++++++---- src/PolarisedSum.cpp | 2 +- 9 files changed, 39 insertions(+), 25 deletions(-) diff --git a/AmpGen/BinDT.h b/AmpGen/BinDT.h index 2201e8f36d2..386c55a6cad 100644 --- a/AmpGen/BinDT.h +++ b/AmpGen/BinDT.h @@ -15,9 +15,9 @@ #include #include "AmpGen/ArgumentPack.h" -#include "AmpGen/EventList.h" #include "AmpGen/MsgService.h" #include "AmpGen/Types.h" +#include "AmpGen/EventList.h" namespace AmpGen { diff --git a/AmpGen/Chi2Estimator.h b/AmpGen/Chi2Estimator.h index 4f59291ca85..841cfa76cc7 100644 --- a/AmpGen/Chi2Estimator.h +++ b/AmpGen/Chi2Estimator.h @@ -7,19 +7,30 @@ #include "AmpGen/BinDT.h" +#if ENABLE_AVX2 +#include "AmpGen/EventListSIMD.h" +#else +#include "AmpGen/EventList.h" +#endif + + namespace AmpGen { - class EventList; class EventType; class Event; class Chi2Estimator { - public: + #if ENABLE_AVX2 + typedef EventListSIMD EventList_type; + #else + typedef EventList EventList_type; + #endif + public: template - Chi2Estimator( const EventList& dataEvents, const EventList& mcEvents, + Chi2Estimator( const EventList_type& dataEvents, const EventList_type& mcEvents, const std::function& fcn, - const argument_types&... args ) : m_binning(dataEvents, ArgumentPack(args...) ) + const argument_types&... args ) : m_binning(dataEvents.begin(), dataEvents.end(), ArgumentPack(args...) ) { doChi2(dataEvents, mcEvents, fcn); } @@ -27,7 +38,7 @@ namespace AmpGen double chi2() const; double nBins() const; void writeBinningToFile( const std::string& filename ); - void doChi2( const EventList& dataEvents, const EventList& mcEvents, + void doChi2( const EventList_type& dataEvents, const EventList_type& mcEvents, const std::function& fcn ); private: double m_chi2; diff --git a/AmpGen/Store.h b/AmpGen/Store.h index ddfb9b0d5da..0a0f8f0e448 100644 --- a/AmpGen/Store.h +++ b/AmpGen/Store.h @@ -135,10 +135,10 @@ namespace AmpGen { std::map> m_index; }; } -//using aos_store = AmpGen::Store; -//using soa_store = AmpGen::Store; -// -//ENABLE_DEBUG(aos_store) -//ENABLE_DEBUG(soa_store) +using aos_store = AmpGen::Store; +using soa_store = AmpGen::Store; + +ENABLE_DEBUG(aos_store) +ENABLE_DEBUG(soa_store) #endif diff --git a/AmpGen/SumPDF.h b/AmpGen/SumPDF.h index cc0d466bca2..b5d4e70eee3 100644 --- a/AmpGen/SumPDF.h +++ b/AmpGen/SumPDF.h @@ -116,7 +116,7 @@ namespace AmpGen auto eval = pdf.evaluator(events); for( unsigned i = 0; i != events->size(); ++i ) values[i] += eval( events->at(i) ); } ); - return arrayToFunctor(values, events); + return arrayToFunctor(values); } KeyedView componentEvaluator(const eventListType* events) const { diff --git a/examples/SignalOnlyFitter.cpp b/examples/SignalOnlyFitter.cpp index 3d3932e573e..ef256081c11 100644 --- a/examples/SignalOnlyFitter.cpp +++ b/examples/SignalOnlyFitter.cpp @@ -150,9 +150,9 @@ FitResult* doFit( likelihoodType&& likelihood, EventList_type& data, EventList_t /* Estimate the chi2 using an adaptive / decision tree based binning, down to a minimum bin population of 15, and add it to the output. */ - //Chi2Estimator chi2( data, mc, likelihood.evaluator(&mc), MinEvents(15), Dim(data.eventType().dof()) ); - //chi2.writeBinningToFile("chi2_binning.txt"); - //fr->addChi2( chi2.chi2(), chi2.nBins() ); + Chi2Estimator chi2( data, mc, likelihood.evaluator(&mc), MinEvents(15), Dim(data.eventType().dof()) ); + chi2.writeBinningToFile("chi2_binning.txt"); + fr->addChi2( chi2.chi2(), chi2.nBins() ); fr->print(); /* Make the plots for the different components in the PDF, i.e. the signal and backgrounds. diff --git a/src/Chi2Estimator.cpp b/src/Chi2Estimator.cpp index a94b04fdc67..6c5ee020aef 100644 --- a/src/Chi2Estimator.cpp +++ b/src/Chi2Estimator.cpp @@ -6,9 +6,9 @@ #include "AmpGen/ArgumentPack.h" #include "AmpGen/EventType.h" #include "AmpGen/MsgService.h" -#include "AmpGen/EventList.h" #include "AmpGen/Event.h" + using namespace AmpGen; struct Moment { @@ -37,7 +37,7 @@ double Chi2Estimator::chi2() const { return m_chi2; } double Chi2Estimator::nBins() const { return m_nBins; } void Chi2Estimator::writeBinningToFile( const std::string& filename ) { m_binning.serialize( filename ); } -void Chi2Estimator::doChi2( const EventList& dataEvents, const EventList& mcEvents, +void Chi2Estimator::doChi2( const EventList_type& dataEvents, const EventList_type& mcEvents, const std::function& fcn ) { std::vector data( m_binning.size() ); @@ -48,7 +48,7 @@ void Chi2Estimator::doChi2( const EventList& dataEvents, const EventList& mcEv unsigned int j = 0; double total_data_weight = 0; double total_int_weight = 0; - for ( auto& d : dataEvents ) { + for ( const auto& d : dataEvents ) { if ( j % 1000000 == 0 && j != 0 ) INFO( "Binned " << j << " data events" ); double w = d.weight(); data[m_binning.getBinNumber( d )].add( d.weight() ); diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index ad957579520..75fd7a19571 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -343,7 +343,7 @@ std::function CoherentSum::evaluator(const EventList_type* { auto events = ievents == nullptr ? m_integrator.events() : ievents; Store store( events->size(), m_matrixElements); - for( auto& me : m_matrixElements ) store.update(m_events->store(), me ); + for( auto& me : m_matrixElements ) store.update(events->store(), me ); std::vector values( events->aligned_size() ); #ifdef _OPENMP @@ -356,7 +356,7 @@ std::function CoherentSum::evaluator(const EventList_type* amp = amp + m_matrixElements[j].coefficient * store(block, j); utils::store( values.data() + block * utils::size::value, (m_weight/m_norm) * utils::norm(amp) ); } - return arrayToFunctor(values); + return arrayToFunctor(values); } KeyedView CoherentSum::componentEvaluator(const EventList_type* ievents) const diff --git a/src/EventListSIMD.cpp b/src/EventListSIMD.cpp index 0492917bf82..4f791f5edf4 100644 --- a/src/EventListSIMD.cpp +++ b/src/EventListSIMD.cpp @@ -116,10 +116,13 @@ void EventListSIMD::loadFromTree( TTree* tree, const ArgumentPack& args ) for( unsigned k = 0 ; k != float_v::size; ++k ) { auto evt = k + block * float_v::size; - if(evt >= m_data.size() ) break; - tr.getEntry( hasEventList ? entryList[evt] : evt ); - if( applySym ) symmetriser( temp ); - buffer[k] = temp; + if(evt < m_data.size() ) + { + tr.getEntry( hasEventList ? entryList[evt] : evt ); + if( applySym ) symmetriser( temp ); + buffer[k] = temp; + } + else buffer[k].setWeight(0); } gather( buffer, block ); } diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 19bb114c96a..ba4c1cf10e0 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -488,7 +488,7 @@ std::function PolarisedSum::evaluator(const EventList_type { auto events = ievents == nullptr ? m_integrator.events() : ievents; Store store( events->size(), m_matrixElements); - for( auto& me : m_matrixElements ) store.update(m_events->store(), me ); + for( auto& me : m_matrixElements ) store.update(events->store(), me ); std::vector values( events->aligned_size() ); #ifdef _OPENMP From 53a3917b273cede07a21275725c24b9beb5e988e Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 15 Apr 2020 19:11:17 +0200 Subject: [PATCH 168/250] fixes for array / splines for avx2d --- AmpGen/AmplitudeRules.h | 12 +++---- AmpGen/CoherentSum.h | 13 ++++--- AmpGen/MetaUtils.h | 1 + AmpGen/MsgService.h | 23 +++++++------ AmpGen/ProfileClock.h | 3 +- AmpGen/Store.h | 11 +++--- AmpGen/SumPDF.h | 1 + AmpGen/simd/avx2d_types.h | 67 +++++++++++++++++++++++------------- AmpGen/simd/utils.h | 2 +- apps/ConvertToSourceCode.cpp | 4 +-- src/Array.cpp | 5 +++ src/CoherentSum.cpp | 39 ++++++++++++++------- src/EventListSIMD.cpp | 7 ++-- src/ProgressBar.cpp | 4 ++- test/test_avx2d.cpp | 64 ++++++++++++++++++++++++++++++++++ 15 files changed, 186 insertions(+), 70 deletions(-) create mode 100644 test/test_avx2d.cpp diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index d65df6bf7d0..27a3be5991c 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -89,19 +89,19 @@ namespace AmpGen { using amp_type = CompiledExpression; TransitionMatrix() = default; - TransitionMatrix(Particle dt, + TransitionMatrix(const Particle& dt, const TotalCoupling& coupling, const amp_type& amp) : amp_type(amp), decayTree(dt), coupling(coupling) {} - TransitionMatrix(Particle dt, + TransitionMatrix(const Particle& dt, const TotalCoupling& coupling, const MinuitParameterSet& mps, const std::map& evtFormat, const bool& debugThis=false) : - amp_type(dt.getExpression(debugThis ? &db : nullptr ), dt.decayDescriptor(), evtFormat, db, &mps ), + amp_type(Particle(dt).getExpression(debugThis ? &db : nullptr ), dt.decayDescriptor(), evtFormat, db, &mps ), decayTree(dt), coupling(coupling) {} @@ -154,19 +154,19 @@ namespace AmpGen { using amp_type = CompiledExpression; TransitionMatrix() = default; - TransitionMatrix(Particle dt, + TransitionMatrix(const Particle& dt, const TotalCoupling& coupling, const amp_type& amp) : amp_type(amp), decayTree(dt), coupling(coupling) {} - TransitionMatrix(Particle dt, + TransitionMatrix(const Particle& dt, const TotalCoupling& coupling, const MinuitParameterSet& mps, const std::map& evtFormat, const bool& debugThis=false) : - amp_type(dt.getExpression(debugThis ? &db : nullptr ), dt.decayDescriptor(), evtFormat, db, &mps ), + amp_type(Particle(dt).getExpression(debugThis ? &db : nullptr ), dt.decayDescriptor(), evtFormat, db, &mps ), decayTree(dt), coupling(coupling) { use_rto();} diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index 89bd84cb3f6..1db5690704d 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -74,14 +74,14 @@ namespace AmpGen void setWeight( MinuitProxy param ) { m_weight = param; } void makeTotalExpression(); void reset( bool resetEvents = false ); - void setEvents( EventList_type& list ); + void setEvents( const EventList_type& list ); + void setMC( const EventList_type& sim ); #if ENABLE_AVX2 - void setEvents( EventList& list) { m_ownEvents = true; setEvents( *(new EventListSIMD(list)) ) ; } - void setMC( EventList& list) { setMC( *(new EventListSIMD(list)) ) ; } + void setEvents( const EventList& list) { m_ownEvents = true; setEvents( *(new EventListSIMD(list)) ) ; } + void setMC( const EventList& list) { setMC( *(new EventListSIMD(list)) ) ; } #endif float_v operator()(const float_v*, const unsigned) const; real_t operator()(const Event& evt ) const { return m_weight*std::norm(getVal(evt))/m_norm; } - void setMC( EventList_type& sim ); void debug( const Event& evt, const std::string& nameMustContain=""); void generateSourceCode( const std::string& fname, const double& normalisation = 1, bool add_mt = false ); @@ -101,7 +101,7 @@ namespace AmpGen AmplitudeRules m_rules; ///< Ruleset for the selected transition. Integrator m_integrator; ///< Tool to calculate integrals - EventList_type* m_events = {nullptr}; ///< Data events to evaluate PDF on + const EventList_type* m_events = {nullptr}; ///< Data events to evaluate PDF on Store m_cache; ///< Store of intermediate values for the PDF calculation bool m_ownEvents = {false}; ///< Flag as to whether events are owned by this PDF or not @@ -116,7 +116,10 @@ namespace AmpGen bool m_verbosity = {false}; ///< Flag for verbose printing std::string m_objCache = {""}; ///< Directory that contains (cached) amplitude objects std::string m_prefix = {""}; ///< Prefix for matrix elements + const MinuitParameterSet* m_mps = {nullptr}; + void addMatrixElement( std::pair& particleWithCoupling, const MinuitParameterSet& mps ); + }; } // namespace AmpGen diff --git a/AmpGen/MetaUtils.h b/AmpGen/MetaUtils.h index 20b6ac06253..1450998d3e1 100644 --- a/AmpGen/MetaUtils.h +++ b/AmpGen/MetaUtils.h @@ -83,6 +83,7 @@ namespace AmpGen { return std::is_constructible::value && (false == std::is_same::value); } + template std::vector typelist() { diff --git a/AmpGen/MsgService.h b/AmpGen/MsgService.h index 3067529e460..3d91b75d63f 100644 --- a/AmpGen/MsgService.h +++ b/AmpGen/MsgService.h @@ -17,10 +17,11 @@ #include #define WARNINGLEVEL 1 -#define FCNNAMELENGTH 45 namespace AmpGen { namespace detail { + constexpr static int FCNNAMELENGTH = 45; + inline std::string trimmedString( std::string thing, const unsigned int& length = FCNNAMELENGTH ) { size_t pos2=0; @@ -42,6 +43,10 @@ namespace AmpGen { } return thing.size() < length ? thing : thing.substr( 0, length ) + "..."; } + inline std::ostream& labelled_stream(const std::string& function_name) + { + return std::cout << "\033[2;34m" << std::left << std::setw(FCNNAMELENGTH) << trimmedString(function_name) << " INFO " << "\033[0m"; + } template struct debug_type : std::false_type {}; } } @@ -53,38 +58,36 @@ namespace AmpGen { /// Used for printing verbose debugging messages, only if DEBUGLEVEL is defined. #define DEBUG( X ) { \ if constexpr( AmpGen::detail::debug_type::type>::value ) { \ - std::cout << "\033[2;32m" << std::left << std::setw( FCNNAMELENGTH ) << AmpGen::detail::trimmedString(__PRETTY_FUNCTION__) \ + std::cout << "\033[2;32m" << std::left << std::setw( AmpGen::detail::FCNNAMELENGTH ) << AmpGen::detail::trimmedString(__PRETTY_FUNCTION__) \ << " DEBUG " \ << "\033[0m" << X << " " << std::endl; } } /// @ingroup msgService macro INFO /// Used for printing information messages, and will always be printed. -#define INFO( X ) \ - std::cout << "\033[2;34m" << std::left << std::setw( FCNNAMELENGTH ) << detail::trimmedString( __PRETTY_FUNCTION__ ) \ - << " INFO " \ - << "\033[0m" << X << std::endl +#define INFO( X ) \ + AmpGen::detail::labelled_stream(__PRETTY_FUNCTION__) << X << std::endl /// @ingroup msgService macro ERROR /// Used for printing errors messages, and will always be printed. #define ERROR( X ) \ - std::cout << "\033[1;31m" << std::left << std::setw( FCNNAMELENGTH ) << detail::trimmedString( __PRETTY_FUNCTION__ ) \ + std::cout << "\033[1;31m" << std::left << std::setw( AmpGen::detail::FCNNAMELENGTH ) << AmpGen::detail::trimmedString( __PRETTY_FUNCTION__ ) \ << " ERROR " \ << "\033[0m" << X << std::endl /// @ingroup msgService macro FATAL /// Used for printing fatal errors messages, and will always be printed and will terminate the process afterwards. #define FATAL( X ) \ -{ std::cout << "\033[1;31m" << std::left << std::setw( FCNNAMELENGTH ) << detail::trimmedString( __PRETTY_FUNCTION__ ) \ +{ std::cout << "\033[1;31m" << std::left << std::setw( AmpGen::detail::FCNNAMELENGTH ) << AmpGen::detail::trimmedString( __PRETTY_FUNCTION__ ) \ << " FATAL " \ << "\033[0m" << X << std::endl; \ - throw std::runtime_error( detail::trimmedString( __PRETTY_FUNCTION__)+ " FATAL" ) ;} + throw std::runtime_error( AmpGen::detail::trimmedString( __PRETTY_FUNCTION__)+ " FATAL" ) ;} /// @ingroup msgService macro FATAL /// Used for printing warning messages, can be switched off using WARNINGLEVEL. These messages are often harmless, but sometimes not! #ifdef WARNINGLEVEL #define WARNING( X ) \ - std::cout << "\033[1;35m" << std::left << std::setw( FCNNAMELENGTH ) << detail::trimmedString( __PRETTY_FUNCTION__ ) \ + std::cout << "\033[1;35m" << std::left << std::setw( AmpGen::detail::FCNNAMELENGTH ) << AmpGen::detail::trimmedString( __PRETTY_FUNCTION__ ) \ << " WARNING " \ << "\033[0m" << X << std::endl #else diff --git a/AmpGen/ProfileClock.h b/AmpGen/ProfileClock.h index 2b334861f9c..6da6bccbaa9 100644 --- a/AmpGen/ProfileClock.h +++ b/AmpGen/ProfileClock.h @@ -1,6 +1,7 @@ #ifndef AMPGEN_PROFILECLOCK_H #define AMPGEN_PROFILECLOCK_H 1 #include +#include #include "AmpGen/MsgService.h" #include "AmpGen/Utilities.h" @@ -44,7 +45,7 @@ namespace AmpGen{ tmax = pi > tmax ? pi : tmax; } t /= double(N); - t2 = sqrt( t2 / double(N) - t*t); + t2 = std::sqrt( t2 / double(N) - t*t); INFO( (name == "" ? typeof() : name ) << " " << t << " ± " << t2 << "[ms] per iteration << [" << tmin << ", " << tmax << "]" ); return t; } diff --git a/AmpGen/Store.h b/AmpGen/Store.h index 0a0f8f0e448..4ffccf44fb0 100644 --- a/AmpGen/Store.h +++ b/AmpGen/Store.h @@ -19,10 +19,10 @@ namespace AmpGen { m_nFields(nFields), m_store(m_nBlocks * m_nFields) {} - template Store( const Store& store, const std::vector& functors, const size_t& fieldsPerFunctor=0) - : Store(store.size(), functors, fieldsPerFunctor){ - for( auto& f : functors ) update(store,f); - } + // template Store( const Store& store, const std::vector& functors, const size_t& fieldsPerFunctor=0) + // : Store(store.size(), functors, fieldsPerFunctor){ + // for( auto& f : functors ) update(store,f); + // } template Store( const size_t& nEntries, const std::vector& functors, const size_t& fieldsPerFunctor = 0) { @@ -135,10 +135,11 @@ namespace AmpGen { std::map> m_index; }; } +/* using aos_store = AmpGen::Store; using soa_store = AmpGen::Store; ENABLE_DEBUG(aos_store) ENABLE_DEBUG(soa_store) - +*/ #endif diff --git a/AmpGen/SumPDF.h b/AmpGen/SumPDF.h index b5d4e70eee3..a2ef9e1a73f 100644 --- a/AmpGen/SumPDF.h +++ b/AmpGen/SumPDF.h @@ -16,6 +16,7 @@ namespace AmpGen { class EventList; + class EventListSIMD; /** @class SumPDF @brief A pdf that contains one or more terms. diff --git a/AmpGen/simd/avx2d_types.h b/AmpGen/simd/avx2d_types.h index 594b95dcedc..6326576cdbe 100644 --- a/AmpGen/simd/avx2d_types.h +++ b/AmpGen/simd/avx2d_types.h @@ -10,14 +10,22 @@ namespace AmpGen { namespace AVX2d { + #define stl_fallback( x ) \ + inline float_t x( const float_t& v ){ auto a = v.to_array(); return float_t( std::x(a[0]), std::x(a[1]), std::x(a[2]), std::x(a[3]) ) ; } + struct float_t { __m256d data; static constexpr unsigned size = 4; typedef double scalar_type; float_t() = default; float_t(__m256d data ) : data(data) {} - float_t(const double& f ) : data( _mm256_set1_pd( f )) {} - float_t(const double* f ) : data( _mm256_loadu_pd( f ) ) {} + float_t(const double& f ) : data( _mm256_set1_pd( f )) {} + float_t(const double& x0, const double& x1, const double& x2, const double& x3 ) + { + double tmp[4] = {x0,x1,x2,x3}; + _mm256_loadu_pd(tmp); + } + float_t(const double* f ) : data( _mm256_loadu_pd( f ) ) {} void store( double* ptr ) const { _mm256_storeu_pd( ptr, data ); } std::array to_array() const { std::array b; store( &b[0] ); return b; } double at(const unsigned i) const { return to_array()[i] ; } @@ -43,27 +51,43 @@ namespace AmpGen { inline float_t operator>( const float_t& lhs, const float_t& rhs ) { return _mm256_cmp_pd( lhs, rhs, _CMP_GT_OS ); } inline float_t operator==( const float_t& lhs, const float_t& rhs ){ return _mm256_cmp_pd( lhs, rhs, _CMP_EQ_OS ); } inline float_t sqrt( const float_t& v ) { return _mm256_sqrt_pd(v); } + inline float_t abs ( const float_t& v ) { return _mm256_andnot_pd(_mm256_set1_pd(-0.), v); } // inline float_t sin( const float_t& v ) { return sin256_pd(v) ; } // inline float_t cos( const float_t& v ) { return cos256_pd(v) ; } // inline float_t tan( const float_t& v ) { float_t s; float_t c; sincos256_pd(v, (__m256*)&s, (__m256*)&c) ; return s/c; } // inline float_t log( const float_t& v ) { return log256_ps(v) ; } // inline float_t exp( const float_t& v ) { return exp256_ps(v) ; } - inline float_t abs ( const float_t& v ) { - static const __m256d sign_mask = _mm256_set1_pd(-0.); // -0. = 1 << 63 - return _mm256_andnot_pd(sign_mask, v); - } inline float_t select(const float_t& mask, const float_t& a, const float_t& b ) { return _mm256_blendv_pd( b, a, mask ); } inline float_t select(const bool& mask , const float_t& a, const float_t& b ) { return mask ? a : b; } inline float_t atan2( const float_t& y, const float_t& x ){ - std::array bx{x.to_array()}, by{y.to_array()}, rt; - for( unsigned i = 0 ; i != 4 ; ++i ) rt[i] = std::atan2( by[i] , bx[i] ); - return float_t (rt.data() ); + std::array bx{x.to_array()}, by{y.to_array()}; + return float_t ( + std::atan2( by[0], bx[0]) + , std::atan2( by[1], bx[1]) + , std::atan2( by[2], bx[2]) + , std::atan2( by[3], bx[3]) ); + } + inline __m256i double_to_int( const float_t& x ) + { + // based on: https://stackoverflow.com/questions/41144668/how-to-efficiently-perform-double-int64-conversions-with-sse-avx + return _mm256_sub_epi64(_mm256_castpd_si256(x + _mm256_set1_pd(0x0018000000000000)), + _mm256_castpd_si256(_mm256_set1_pd(0x0018000000000000))); } - inline float_t log( const float_t& x ) + inline float_t gather( const double* base_addr, const float_t& offsets) + { + return _mm256_i64gather_pd(base_addr, double_to_int(offsets),sizeof(double)); + } + stl_fallback( log ) + stl_fallback( exp ) + stl_fallback( tan ) + stl_fallback( sin ) + stl_fallback( cos ) + + inline float_t remainder( const float_t& a, const float_t& b ){ return a - _mm256_round_pd(a/b, _MM_FROUND_TO_NEG_INF) * b; } + inline float_t fmod( const float_t& a, const float_t& b ) { - std::array bx{x.to_array()}, rt; - for( unsigned i = 0 ; i != 4 ; ++i ) rt[i] = std::log(bx[i]); - return float_t (rt.data()); + auto r = remainder( abs(a), abs(b) ); + return select( a > 0., r, -r ); } struct complex_t { @@ -123,22 +147,17 @@ namespace AmpGen { inline complex_t select(const float_t& mask, const complex_t& a, const float_t& b ) { return complex_t( select(mask, a.re, b ) , select(mask, a.im, 0.f) ); } inline complex_t select(const bool& mask , const complex_t& a, const complex_t& b ) { return mask ? a : b; } inline complex_t exp( const complex_t& v ){ - // float_t s; float_t c; sincos256_ps(v.im, (__m256*)&s, (__m256*)&c); - auto vr = v.re.to_array(); - auto vi = v.im.to_array(); - std::array rt_re; - std::array rt_im; - for( unsigned i = 0 ; i != 4; ++i ){ - rt_re[i] = std::exp( vr[i] ) * cos( vi[i] ); - rt_im[i] = std::exp( vr[i] ) * sin( vi[i] ); - // rt[i] = complex_t( exp(vr[i]) * cos(vi[i]), exp(vr[i]) * sin( vi[i] ) ); - } - return complex_t( rt_re.data(), rt_im.data() ); + return exp( v.re) * complex_t( cos( v.im ), sin( v.im ) ); } inline float_t fmadd( const float_t& a, const float_t& b, const float_t& c ) { return _mm256_fmadd_pd(a, b, c ); } + inline complex_t sqrt( const complex_t& v ) + { + auto r = abs(v); + return complex_t ( sqrt( 0.5 * (r + v.re) ), sqrt( 0.5*( r - v.re ) ) ); + } inline std::ostream& operator<<( std::ostream& os, const complex_t& obj ) { return os << "( "<< obj.re << ") (" << obj.im << ")"; } #pragma omp declare reduction(+: float_t: \ diff --git a/AmpGen/simd/utils.h b/AmpGen/simd/utils.h index 094877931b2..62099046210 100644 --- a/AmpGen/simd/utils.h +++ b/AmpGen/simd/utils.h @@ -45,7 +45,7 @@ namespace AmpGen { template <> struct is_vector_type : std::false_type {}; #endif template simd_type gather( - const container_type& container, const functor_type& functor, unsigned offset=0, float df =0.) + const container_type& container, const functor_type& functor, unsigned offset=0, typename simd_type::scalar_type df =0.) { std::array rv; if( df == 0. ) diff --git a/apps/ConvertToSourceCode.cpp b/apps/ConvertToSourceCode.cpp index c6864aca788..94ffd3f8567 100644 --- a/apps/ConvertToSourceCode.cpp +++ b/apps/ConvertToSourceCode.cpp @@ -73,8 +73,8 @@ void create_integration_tests(T& pdf, template void generate_source(T& pdf, EventList& normEvents, const std::string& sourceFile, MinuitParameterSet& mps, const double& sf) { - bool normalise = NamedParameter("Normalise",true); - std::string type = NamedParameter( "Type", "CoherentSum" ); + bool normalise = NamedParameter("Normalise",true); + std::string type = NamedParameter("Type", "CoherentSum" ); double norm = 1; if( normalise ){ diff --git a/src/Array.cpp b/src/Array.cpp index f4bdb97412a..4a135861e7e 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -21,7 +21,12 @@ std::string Array::to_string(const ASTResolver* resolver) const { auto head = m_top.to_string(resolver); if( is(m_address) ) return head+"["+ std::to_string(int(std::real(m_address()))) +"]"; + auto offset = m_address.to_string(resolver); + if( resolver != nullptr && resolver->enableAVX() ) + { + return " gather( &(" + head + "), " + offset + ")"; + } auto pos = head.find_last_of("]"); if( pos != std::string::npos ){ auto st1 = head.substr(0,pos); diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 75fd7a19571..910b3c73711 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -34,14 +34,17 @@ using namespace AmpGen; CoherentSum::CoherentSum() = default; +//ENABLE_DEBUG(CoherentSum) + CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, const std::string& prefix ) - : m_rules (mps) + : m_rules (mps) , m_evtType (type) , m_printFreq(NamedParameter( "CoherentSum::PrintFrequency", 100) ) , m_dbThis (NamedParameter( "CoherentSum::Debug" , false)) , m_verbosity(NamedParameter( "CoherentSum::Verbosity" , 0) ) - , m_objCache (NamedParameter("CoherentSum::ObjectCache" ,"") ) + , m_objCache (NamedParameter("CoherentSum::ObjectCache" ,"") ) , m_prefix (prefix) + , m_mps(&mps) { auto amplitudes = m_rules.getMatchingRules( m_evtType, prefix); if( amplitudes.size() == 0 ){ @@ -52,15 +55,19 @@ CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, m_normalisations.resize( m_matrixElements.size(), m_matrixElements.size() ); size_t nThreads = NamedParameter ("nCores" , std::thread::hardware_concurrency(), "Number of threads to use" ); ThreadPool tp(nThreads); - //#pragma omp parallel for for(size_t i = 0; i < m_matrixElements.size(); ++i){ - tp.enqueue( [i,this,&mps,&litudes]{ - m_matrixElements[i] = TransitionMatrix( amplitudes[i].first, amplitudes[i].second, mps, this->m_evtType.getEventFormat(), this->m_dbThis); - CompilerWrapper().compile( m_matrixElements[i], this->m_objCache); } ); + tp.enqueue( [i,this,&mps,&litudes]{ + auto& [p, c] = amplitudes[i]; + m_matrixElements[i] = + TransitionMatrix(p, c, + CompiledExpression( + p.getExpression(), p.decayDescriptor(), + this->m_evtType.getEventFormat(), DebugSymbols(), this->m_mps ) ); + CompilerWrapper().compile( m_matrixElements[i], this->m_objCache); + } ); } } - void CoherentSum::prepare() { transferParameters(); @@ -75,7 +82,7 @@ void CoherentSum::prepare() } clockEval.stop(); ProfileClock clockIntegral; - if ( m_integrator.isReady()) updateNorms(); + if (m_integrator.isReady()) updateNorms(); else if ( m_verbosity ) WARNING( "No simulated sample specified for " << this ); clockIntegral.stop(); if ( m_verbosity && m_prepareCalls % 100 == 0 ) { @@ -175,8 +182,13 @@ void CoherentSum::generateSourceCode(const std::string& fname, const double& nor bool includePythonBindings = NamedParameter("CoherentSum::IncludePythonBindings",false); for ( auto& p : m_matrixElements ){ - stream << p << std::endl; - p.compileWithParameters( stream ); + auto expr = CompiledExpression( + p.expression(), + p.decayDescriptor(), + m_evtType.getEventFormat(), DebugSymbols() , m_mps ); + expr.prepare(); + stream << expr << std::endl; + expr.compileWithParameters( stream ); if( includePythonBindings ) p.compileDetails( stream ); } Expression event = Parameter("x0",0,true); @@ -254,17 +266,18 @@ void CoherentSum::reset( bool resetEvents ) } } -void CoherentSum::setEvents( EventList_type& list ) +void CoherentSum::setEvents( const EventList_type& list ) { - if ( m_verbosity ) INFO( "Setting event list with:" << list.size() << " events for " << this ); + DEBUG( "Setting event list with:" << list.size() << " events for " << this ); reset(); + for( auto& me : m_matrixElements ){ DEBUG("Registering: " << me.name() ) ; } if( m_ownEvents && m_events != nullptr ) delete m_events; m_events = &list; m_cache = Store( m_events->size(), m_matrixElements ); } -void CoherentSum::setMC( EventList_type& sim ) +void CoherentSum::setMC( const EventList_type& sim ) { if ( m_verbosity ) INFO( "Setting norm. event list with:" << sim.size() << " events for " << this ); reset(); diff --git a/src/EventListSIMD.cpp b/src/EventListSIMD.cpp index 4f791f5edf4..3c7a644c34c 100644 --- a/src/EventListSIMD.cpp +++ b/src/EventListSIMD.cpp @@ -33,6 +33,8 @@ #include "AmpGen/simd/utils.h" using namespace AmpGen; +// ENABLE_DEBUG(EventListSIMD) + EventListSIMD::EventListSIMD( const EventType& type ) : m_eventType( type ) {} void EventListSIMD::loadFromFile( const std::string& fname, const ArgumentPack& args ) @@ -134,14 +136,15 @@ void EventListSIMD::loadFromTree( TTree* tree, const ArgumentPack& args ) EventListSIMD::EventListSIMD( const EventList& other ) : EventListSIMD( other.eventType() ) { m_data = Store(other.size(), m_eventType.eventSize() ); + DEBUG("Converting EventList -> EventListSIMD, allocate: " << m_data.size() << " events in " << m_data.nBlocks() << " with: " << m_data.nFields() << " fields"); m_weights.resize( m_data.nBlocks() ); m_genPDF.resize ( m_data.nBlocks() ); for( unsigned block = 0 ; block != m_data.nBlocks(); block++ ) { for( unsigned j = 0 ; j != m_data.nFields(); ++j ) - m_data(block, j ) = utils::gather(other, [j](auto& event){ return event[j]; } , block * float_v::size ); + m_data(block, j) = utils::gather(other, [j](auto& event){ return event[j]; } , block * float_v::size ); m_weights[block] = utils::gather(other, [](auto& event){ return event.weight(); }, block * float_v::size, 0); - m_genPDF [block] = utils::gather(other, [](auto& event){ return event.genPdf(); }, block * float_v::size, 1 ); + m_genPDF [block] = utils::gather(other, [](auto& event){ return event.genPdf(); }, block * float_v::size, 1); } } diff --git a/src/ProgressBar.cpp b/src/ProgressBar.cpp index 84ba994f132..73e940e5855 100644 --- a/src/ProgressBar.cpp +++ b/src/ProgressBar.cpp @@ -21,8 +21,10 @@ void ProgressBar::print(const double& percentage, const std::string& message) int val = int(percentage * 100); if( val == m_lastPercent ) return; m_lastPercent = val; - std::cout << "\r\033[2;34m" << std::left << std::setw( FCNNAMELENGTH ) << m_context << " INFO " << "\033[0m"; + std::cout << "\r\033[2;34m" << std::left << std::setw( detail::FCNNAMELENGTH ) << m_context << " INFO " << "\033[0m"; std::cout << "Completed: " << std::right << std::setw(3) << val << "% " << "["; + + // detail::labelled_stream(m_context) << "Completed: " << std::right << std::setw(3) << val << "% " << "["; std::fill_n(std::ostream_iterator(std::cout), lpad, '|'); std::fill_n(std::ostream_iterator(std::cout), m_width-lpad, ' '); std::cout << "]"; diff --git a/test/test_avx2d.cpp b/test/test_avx2d.cpp new file mode 100644 index 00000000000..20119f426e8 --- /dev/null +++ b/test/test_avx2d.cpp @@ -0,0 +1,64 @@ + +#define BOOST_TEST_DYN_LINK + +#define BOOST_TEST_MODULE "test_avx2" + +#include +namespace utf = boost::unit_test; + + +#if ENABLE_AVX2 +#include "AmpGen/simd/avx2d_types.h" + +using namespace AmpGen; + +BOOST_AUTO_TEST_CASE( test_fmod ) +{ + std::vector a = {5.1, -5.1, 5.1, -5.1}; + std::vector b = {3.0, +3.0, -3.0, -3.0}; + + AVX2d::float_t av( a.data() ); + AVX2d::float_t bv( b.data() ); + + auto modv = AVX2d::fmod(av,bv); + BOOST_TEST_MESSAGE( "fmod = " << modv ); + + auto mod = modv.to_array(); + BOOST_TEST( mod[0] == 2.1 , boost::test_tools::tolerance(1e-15)); + BOOST_TEST( mod[1] == -2.1 , boost::test_tools::tolerance(1e-15)); + BOOST_TEST( mod[2] == 2.1 , boost::test_tools::tolerance(1e-15)); + BOOST_TEST( mod[3] == -2.1 , boost::test_tools::tolerance(1e-15)); +} + +BOOST_AUTO_TEST_CASE( test_double_to_int ) +{ + std::vector a = {17.4, -19.2, 12.1, -4007.3}; + auto f = AVX2d::double_to_int( AVX2d::float_t( a.data() )); + alignas(32) uint64_t t[4]; + _mm256_store_si256( (__m256i*)t, f); + BOOST_TEST( t[0] == 17 ); + BOOST_TEST( t[1] == -19 ); + BOOST_TEST( t[2] == 12 ); + BOOST_TEST( t[3] == -4007 ); +} + +BOOST_AUTO_TEST_CASE( test_gather ) +{ + // 0 1 2 3 4 5 6 + std::vector data = { 15.4, 19.7, 121.8, -15.6, M_PI, sqrt(2), 5.7, 12 }; + std::vector addr = { 0, 5, 3, 3 }; + auto v = AVX2d::gather( data.data(), AVX2d::float_t(addr.data()) ).to_array(); + BOOST_TEST( v[0] == data[0] ); + BOOST_TEST( v[1] == data[5] ); + BOOST_TEST( v[2] == data[3] ); + BOOST_TEST( v[3] == data[3] ); +} + +#else +BOOST_AUTO_TEST_CASE( test_dummy ) +{ + BOOST_TEST( 1 == 1 ); +} +#endif + + From 7ad8e91a2a4ece2af87b82d1667644a64b1447d6 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 15 Apr 2020 20:25:42 +0200 Subject: [PATCH 169/250] fix for OSX --- Standalone.cmake | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Standalone.cmake b/Standalone.cmake index f0248d9c909..ad04032760d 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -166,8 +166,9 @@ if( ENABLE_AVX2 ) endif() if("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" ) - target_link_libraries(AmpGen PUBLIC stdc++) - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -lstdc++") + target_link_libraries(AmpGen PUBLIC stdc++ ) + message(STATUS "Using OSX specific flags: -lm -lstdc++ -lSystem") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -lstdc++ -lSystem") elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") target_link_libraries(AmpGen PUBLIC stdc++) set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -lstdc++") From 462ae542fb9aff04f8de902f7284d937965dbbcb Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 19 Apr 2020 14:41:47 +0200 Subject: [PATCH 170/250] Fix simd'ed integration and plotting --- AmpGen/CoherentSum.h | 4 +- AmpGen/CompiledExpression.h | 6 +- AmpGen/EventListSIMD.h | 6 +- AmpGen/Expression.h | 11 +++ AmpGen/Integrator.h | 100 +++++++++------------ AmpGen/LiteSpan.h | 62 ++++--------- AmpGen/MetaUtils.h | 10 ++- AmpGen/PolarisedSum.h | 4 +- AmpGen/Projection.h | 7 +- AmpGen/Store.h | 49 ++++++----- AmpGen/SumPDF.h | 17 ++-- AmpGen/simd/avx2d_types.h | 58 ++++++++++--- Standalone.cmake | 2 +- examples/FitterWithPolarisation.cpp | 22 ++--- src/AmplitudeRules.cpp | 2 +- src/BinaryExpression.cpp | 7 +- src/CoherentSum.cpp | 43 ++++------ src/Expression.cpp | 23 +++++ src/Integrator.cpp | 33 ++----- src/Minimiser.cpp | 3 + src/PolarisedSum.cpp | 129 ++++++++++++---------------- src/Projection.cpp | 20 ++--- test/test_avx2d.cpp | 12 +++ 23 files changed, 320 insertions(+), 310 deletions(-) diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index 1db5690704d..0dbd08da458 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -21,7 +21,7 @@ #include "AmpGen/Projection.h" #include "AmpGen/MinuitParameter.h" #include "AmpGen/Store.h" - +#include "AmpGen/LiteSpan.h" namespace AmpGen { class LinearErrorPropagator; @@ -93,7 +93,7 @@ namespace AmpGen Bilinears norms() const { return m_normalisations ; } std::function evaluator(const EventList_type* = nullptr) const; - KeyedView componentEvaluator(const EventList_type* = nullptr) const; + KeyedFunctors componentEvaluator(const EventList_type* = nullptr) const; protected: std::vector> m_matrixElements; ///< Vector of matrix elements diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index be6c4eecfaf..1bd41d4d1f7 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -220,13 +220,13 @@ namespace AmpGen rt.prepare(); return rt; } - template - CompiledExpression + template + CompiledExpression make_expression( const Expression& expression, const std::string& name, const MinuitParameterSet& mps ) { - CompiledExpression rt(expression,name,{},{},&mps); + CompiledExpression rt(expression,name,{},{},&mps); rt.compile(); rt.prepare(); return rt; diff --git a/AmpGen/EventListSIMD.h b/AmpGen/EventListSIMD.h index 61873b890c3..248deff8455 100644 --- a/AmpGen/EventListSIMD.h +++ b/AmpGen/EventListSIMD.h @@ -60,9 +60,9 @@ namespace AmpGen EventListSIMD( const EventList& other ); const float_v* data() const { return m_data.data(); } operator Store () const { return m_data ; } - const auto& store() const { return m_data; } - const Event at(const unsigned& p) const { return EventListSIMD::operator[](p) ; } - const float_v* block(const unsigned& p) { return m_data.data() + p * m_data.nFields(); } + const auto& store() const { return m_data; } + const Event at(const unsigned& p) const { return EventListSIMD::operator[](p) ; } + const float_v* block(const unsigned& p) const { return m_data.data() + p * m_data.nFields(); } float_v weight(const unsigned& p) const { return m_weights[p]; } float_v genPDF(const unsigned& p) const { return m_genPDF[p]; } const Event operator[]( const size_t&) const; diff --git a/AmpGen/Expression.h b/AmpGen/Expression.h index 85c3f90dca3..49fe25acc3f 100644 --- a/AmpGen/Expression.h +++ b/AmpGen/Expression.h @@ -194,6 +194,17 @@ namespace AmpGen double m_defaultValue; bool m_resolved; }; + class ComplexParameter : public IExpression { + public: + ComplexParameter( const Parameter& real, const Parameter& imag ); + std::string to_string(const ASTResolver* resolver = nullptr ) const override; + void resolve( ASTResolver& resolver ) const override; + operator Expression() const ; + complex_t operator()() const override; + private: + Parameter m_real; + Parameter m_imag; + }; /** @ingroup ExpressionEngine class Ternary @brief Evaluates the ternary operator. diff --git a/AmpGen/Integrator.h b/AmpGen/Integrator.h index cc98c208031..f1f4f7c6c40 100644 --- a/AmpGen/Integrator.h +++ b/AmpGen/Integrator.h @@ -10,55 +10,19 @@ #include "AmpGen/EventListSIMD.h" #include "AmpGen/EventList.h" -/* - * Calculates Bilinears A_i A_j^* integrated over the phase-space. - * Integrates in blocks of (i,j) such that integrals can be queued and evaluated in blocks - * to optimise cache throughput. - */ - namespace AmpGen -{ - class Bilinears - { - private: - size_t rows; - size_t cols; - std::vector norms; - std::vector markAsZero; - std::vector calculate; - public: - Bilinears( const size_t& r = 0, const size_t& c = 0 ); - complex_t get(const size_t& x, const size_t& y) const; - template - complex_t get(const size_t& x, const size_t& y, T* integ = nullptr, const size_t& kx=0, const size_t& ky=0){ - if( integ != nullptr ) integ->queueIntegral(kx, ky, &norms[x*cols+y]); - /// will return the wrong answer for now, but queues for later.. - return norms[x*cols+y]; - } - void set(const size_t& x, const size_t& y, const complex_t& f ); - void setZero(const size_t& x, const size_t& y); - void resetCalculateFlags(); - complex_t& operator()( const size_t& x, const size_t& y ); - bool isZero(const size_t& x, const size_t& y); - bool workToDo(const size_t& x, const size_t& y) const; - void resize(const size_t& r, const size_t& c = 1 ); - }; - - template struct Integral - { - typedef std::function TransferFCN; - size_t i = {0}; - size_t j = {0}; - TransferFCN transfer; - Integral() = default; - Integral(const size_t& i, const size_t& j, TransferFCN t) - : i(i), j(j), transfer(t) {} - }; - +{ class Integrator { - typedef std::function TransferFCN; - + struct QueuedIntegral + { + QueuedIntegral() = default; + QueuedIntegral(complex_t* result, const unsigned& i, const unsigned& j) + : result(result), i(i), j(j) {} + complex_t* result = {nullptr}; + unsigned i = {0}; + unsigned j = {0}; + }; public: Integrator() = default; @@ -73,21 +37,14 @@ namespace AmpGen float_v norm_acc = 0.; for( size_t i = 0 ; i < events->nBlocks(); ++i ) { - m_weight[i] = events->weight(i) / events->genPDF(i); - norm_acc = norm_acc + m_weight[i]; + m_weight[i] = events->weight(i) / events->genPDF(i); + norm_acc += m_weight[i]; } m_norm = utils::sum_elements(norm_acc); } bool isReady() const; - void queueIntegral(const size_t& c1, - const size_t& c2, - const size_t& i, - const size_t& j, - Bilinears* out, - const bool& sim = true); - void addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ); - void queueIntegral(const size_t& i, const size_t& j, complex_t* result); + void queueIntegral( complex_t* result, const unsigned& i, const unsigned& j ); void flush(); template return_type get( const unsigned& index, const unsigned& evt ) const ; @@ -102,19 +59,44 @@ namespace AmpGen if( m_events != nullptr ) m_cache.update( static_cast(m_events)->store(), expression ); #endif } - template - const T* events() const { return static_cast(m_events) ; } + template const T* events() const { return static_cast(m_events) ; } + const Store& cache() const { return m_cache; } private: static constexpr size_t N = {8}; ///unroll factor size_t m_counter = {0}; /// - std::array, N> m_integrals; + std::array m_integrals; const void* m_events = {nullptr}; std::vector m_weight; Store m_cache; double m_norm = {0}; void integrateBlock(); }; + + class Bilinears + { + private: + size_t rows; + size_t cols; + std::vector norms; + std::vector markAsZero; + std::vector calculate; + public: + Bilinears( const size_t& r = 0, const size_t& c = 0 ); + complex_t get(const size_t& x, const size_t& y) const; + complex_t get(const size_t& x, const size_t& y, Integrator* integ = nullptr, const size_t& kx=0, const size_t& ky=0){ + if( integ != nullptr ) integ->queueIntegral(&norms[x*cols+y], kx, ky ); + /// will return the wrong answer for now, but queues for later.. + return norms[x*cols+y]; + } + void set(const size_t& x, const size_t& y, const complex_t& f ); + void setZero(const size_t& x, const size_t& y); + void resetCalculateFlags(); + complex_t& operator()( const size_t& x, const size_t& y ); + bool isZero(const size_t& x, const size_t& y); + bool workToDo(const size_t& x, const size_t& y) const; + void resize(const size_t& r, const size_t& c = 1 ); + }; } // namespace AmpGen #endif diff --git a/AmpGen/LiteSpan.h b/AmpGen/LiteSpan.h index ed4692a015b..e947665a4ef 100644 --- a/AmpGen/LiteSpan.h +++ b/AmpGen/LiteSpan.h @@ -17,54 +17,24 @@ namespace AmpGen { const type* m_data = {nullptr}; unsigned m_size = {0}; }; - /// functor-like object that documents what is stored in each slot; - /// This mutated into a cache-like object as was I was writing it, so - /// should rename it to something else ... - template class KeyedView + + template struct KeyedFunctors { - typedef typename container_type::value_type value_type; - public: - KeyedView( const container_type& container, const unsigned width ) : - m_container(&container), - m_cache( width * container.size(),0 ), - m_width(width), - m_size(container.size()), - m_keys( width, "") {} - unsigned index(const value_type& it) const { return it.index() ; } - const std::string& key(const unsigned int& column ) const { return m_keys[column] ; } - const return_type* operator()( const value_type& it ) const { - if( m_width *index(it) >= m_cache.size()) ERROR("Out-of-bounds access : " << index(it) ); - return &m_cache[m_width * index(it)]; } - const cache_type& operator()(const value_type& it, const unsigned entry ) const { - if( m_width * index(it) + entry > m_cache.size() ) ERROR("Invalid cache element: " << m_width * index(it) + entry > m_cache.size() ); - return m_cache[m_width * index(it) + entry] ; } - unsigned width() const { return m_width ; } + std::vector > functors; + std::vector keys; + std::vector titles; + template + void add(const functor_type& functor, const std::string& key, const std::string& title="") + { + functors.push_back(functor); + keys.push_back(key); + titles.push_back(title); + } + std::vector operator()( const arg_type& arg ) const { - template void set(const functor_type& functor, - unsigned int column, - const std::string& key = "") - { - for(const auto& element : *m_container) m_cache[ element.index() * m_width + column] = functor(element); - if( key != "" ) m_keys[column] = key; - } - cache_type& operator()(const value_type& it, const unsigned entry ) { - auto pos = m_width * index(it) + entry; - if( pos >= m_cache.size() ) ERROR("Out-of-bounds access: " << pos << " " << index(it) + entry); - return m_cache[pos] ; } - void setKey(const unsigned& column, const std::string& key ) { m_keys[column] = key ; } - void print() - { - INFO( "width = " << m_width << ", size = " << m_size << " keys = " << vectorToString( m_keys , " ") << " cache size = " << m_cache.size() ); - for( unsigned int i = 0 ; i != m_width ; ++i ) std::cout << m_cache[i] << " "; - } - private: - const container_type* m_container; - std::vector m_cache; - unsigned m_width; - unsigned m_size; - std::vector m_keys; + std::vector rt; + for( auto& f : functors ) rt.push_back( f(arg) ); + return rt; } }; } diff --git a/AmpGen/MetaUtils.h b/AmpGen/MetaUtils.h index 1450998d3e1..11b33f7ca4f 100644 --- a/AmpGen/MetaUtils.h +++ b/AmpGen/MetaUtils.h @@ -6,6 +6,7 @@ #include #include #include +#include namespace AmpGen { @@ -24,7 +25,7 @@ namespace AmpGen return name; } - template std::string typeof( TYPE t ) { return typeof(); } + template std::string typeof( const TYPE& t ) { return typeof(); } namespace detail { template struct zeroType { typedef T type; }; @@ -43,6 +44,11 @@ namespace AmpGen f( std::get( t ) ); for_each( t, f ); } + template + void for_each_sequence( iterator begin, iterator end, transform_types... transforms) + { + for_each( std::tuple(transforms...), [&](auto& transform){ std::for_each( begin, end, transform ); } ); + } template typename std::enable_if_t @@ -98,6 +104,8 @@ namespace AmpGen template struct isTuple: std::false_type {}; template struct isTuple>: std::true_type {}; + template struct isVector : std::false_type {}; + template struct isVector> : std::true_type {}; } // namespace AmpGen #endif diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index 3bba2f76609..f9908ab196f 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -71,12 +71,13 @@ namespace AmpGen Tensor transitionMatrix(); const TransitionMatrix& operator[](const size_t& i) const { return m_matrixElements[i] ; } std::function evaluator(const EventList_type* = nullptr) const; - KeyedView componentEvaluator(const EventList_type* = nullptr) const; + KeyedFunctors componentEvaluator(const EventList_type* = nullptr) const; private: size_t m_nCalls = {0}; real_t m_norm = {1}; EventList_type* m_events = {nullptr}; Store m_cache = {}; + Store m_pdfCache = {}; bool m_ownEvents = {false}; MinuitParameterSet* m_mps = {nullptr}; MinuitProxy m_weight = {nullptr,1}; @@ -93,7 +94,6 @@ namespace AmpGen std::pair m_dim; std::vector> m_matrixElements; CompiledExpression m_probExpression; - std::vector m_pdfCache; std::vector> indexProduct(const std::vector>&, const std::vector&) const; std::vector polarisations(const std::string&) const ; }; diff --git a/AmpGen/Projection.h b/AmpGen/Projection.h index 2a2481693fa..d1866b373c7 100644 --- a/AmpGen/Projection.h +++ b/AmpGen/Projection.h @@ -11,6 +11,7 @@ #include "THStack.h" #include "AmpGen/ArgumentPack.h" +#include "AmpGen/Types.h" #include "AmpGen/LiteSpan.h" namespace AmpGen @@ -21,6 +22,7 @@ namespace AmpGen class Projection { + using keyedFunctors = KeyedFunctors; public: Projection(); template @@ -35,7 +37,8 @@ namespace AmpGen { return projInternal(evts, ArgumentPack(args...) ); } - template std::tuple, THStack*> operator()(const eventlist_type& evts, const KeyedView& weightFunction, const ARGS... args ) const + template std::tuple, THStack*> operator()(const eventlist_type& evts, + const keyedFunctors& weightFunction, const ARGS... args ) const { return projInternal(evts, weightFunction, ArgumentPack(args...) ); } @@ -52,7 +55,7 @@ namespace AmpGen template TH1D* projInternal(const eventlist_type&, const ArgumentPack&) const; template - std::tuple, THStack*> projInternal(const eventlist_type&, const KeyedView&, const ArgumentPack&) const; + std::tuple, THStack*> projInternal(const eventlist_type&, const keyedFunctors&, const ArgumentPack&) const; std::function m_func; std::string m_name = {""}; std::string m_xAxisTitle = {""}; diff --git a/AmpGen/Store.h b/AmpGen/Store.h index 4ffccf44fb0..d039e2e9f23 100644 --- a/AmpGen/Store.h +++ b/AmpGen/Store.h @@ -18,21 +18,27 @@ namespace AmpGen { m_nBlocks(utils::aligned_size( nEntries ) / utils::size::value ), m_nFields(nFields), m_store(m_nBlocks * m_nFields) {} - - // template Store( const Store& store, const std::vector& functors, const size_t& fieldsPerFunctor=0) - // : Store(store.size(), functors, fieldsPerFunctor){ - // for( auto& f : functors ) update(store,f); - // } - + + template + void addFunctor( const functor_type& functor, unsigned fieldsPerFunctor=0 ) + { + auto vsize = fieldsPerFunctor == 0 ? functor.returnTypeSize() / sizeof(stored_type) : fieldsPerFunctor; + DEBUG("Registering: " << functor.name() << " field = " << m_nFields ); + m_index[ functor.name() ] = std::make_pair(m_nFields, vsize); + m_nFields += vsize; + } + template Store( const size_t& nEntries, const std::vector& functors, const size_t& fieldsPerFunctor = 0) { - for(const auto& functor : functors) - { - auto vsize = fieldsPerFunctor == 0 ? functor.returnTypeSize() / sizeof(stored_type) : fieldsPerFunctor; - DEBUG("Registering: " << functor.name() << " I = " << m_nFields << " / " << functors.size() * vsize ); - m_index[ functor.name() ] = std::make_pair(m_nFields, vsize); - m_nFields += vsize; - } + for(const auto& functor : functors) addFunctor( functor, fieldsPerFunctor); + m_nEntries = nEntries; + m_nBlocks = utils::aligned_size(nEntries)/utils::size::value; + m_store.resize(m_nBlocks * m_nFields); + } + template ::value>::type> + Store( const size_t& nEntries, const functor_type& functor, const size_t& fieldsPerFunctor=0 ) + { + addFunctor(functor); m_nEntries = nEntries; m_nBlocks = utils::aligned_size(nEntries)/utils::size::value; m_store.resize(m_nBlocks * m_nFields); @@ -51,6 +57,11 @@ namespace AmpGen { if constexpr( align == Alignment::SoA ) return m_store[ field * m_nBlocks + index] ; else return m_store[index*m_nFields+field]; } + template + __always_inline const return_type get(const size_t& index, const size_t& field ) const + { + return utils::at( operator()( index / utils::size::value, field ), index % utils::size::value ); + } __always_inline const stored_type* data() const { return m_store.data(); } __always_inline stored_type& operator()(const size_t& index, const size_t& field) { @@ -135,11 +146,9 @@ namespace AmpGen { std::map> m_index; }; } -/* -using aos_store = AmpGen::Store; -using soa_store = AmpGen::Store; - -ENABLE_DEBUG(aos_store) -ENABLE_DEBUG(soa_store) -*/ +// using aos_store = AmpGen::Store; +// using soa_store = AmpGen::Store; +// +// ENABLE_DEBUG(aos_store) +// ENABLE_DEBUG(soa_store) #endif diff --git a/AmpGen/SumPDF.h b/AmpGen/SumPDF.h index a2ef9e1a73f..340f7aa18f9 100644 --- a/AmpGen/SumPDF.h +++ b/AmpGen/SumPDF.h @@ -45,7 +45,7 @@ namespace AmpGen private: typedef typename eventListType::value_type eventValueType; ///< The value type stored in the eventListType std::tuple m_pdfs; ///< The tuple of probability density functions - eventListType* m_events = {nullptr}; ///< The event list to evaluate likelihoods on + const eventListType* m_events = {nullptr}; ///< The event list to evaluate likelihoods on public: /// Default Constructor @@ -75,8 +75,9 @@ namespace AmpGen float_v LL = 0.f; for_each( m_pdfs, []( auto& f ) { f.prepare(); } ); #pragma omp parallel for reduction( +: LL ) - for ( unsigned int block = 0; block < m_events->nBlocks(); ++block ) { - LL += m_events->weight(block) * log(this->operator()(m_events->block(block), block)); + for ( size_t block = 0; block < m_events->nBlocks(); ++block ) + { + LL += m_events->weight(block) * AVX2d::log(this->operator()(m_events->block(block), block)); } return -2 * utils::sum_elements(LL); } @@ -119,12 +120,12 @@ namespace AmpGen } ); return arrayToFunctor(values); } - KeyedView componentEvaluator(const eventListType* events) const + KeyedFunctors componentEvaluator(const eventListType* events) const { - KeyedView view(*events, nPDFs() ); - unsigned pdf_counter = 0; - for_each( this->m_pdfs, [&events, &view, &pdf_counter](const auto& pdf) mutable { - view.set(pdf.evaluator(events), pdf_counter++, typeof(pdf) ); + KeyedFunctors view; + for_each( this->m_pdfs, [&view, &events]( const auto& pdf) mutable { + auto eval = pdf.evaluator(events); + view.add([eval](const auto& event){ return eval(event) ; } , typeof(pdf), "" ); } ); return view; } diff --git a/AmpGen/simd/avx2d_types.h b/AmpGen/simd/avx2d_types.h index 6326576cdbe..46565686a49 100644 --- a/AmpGen/simd/avx2d_types.h +++ b/AmpGen/simd/avx2d_types.h @@ -5,7 +5,6 @@ #include #include #include -#include "AmpGen/simd/avx_mathfun.h" #include namespace AmpGen { @@ -23,7 +22,7 @@ namespace AmpGen { float_t(const double& x0, const double& x1, const double& x2, const double& x3 ) { double tmp[4] = {x0,x1,x2,x3}; - _mm256_loadu_pd(tmp); + data = _mm256_loadu_pd(tmp); } float_t(const double* f ) : data( _mm256_loadu_pd( f ) ) {} void store( double* ptr ) const { _mm256_storeu_pd( ptr, data ); } @@ -55,10 +54,10 @@ namespace AmpGen { // inline float_t sin( const float_t& v ) { return sin256_pd(v) ; } // inline float_t cos( const float_t& v ) { return cos256_pd(v) ; } // inline float_t tan( const float_t& v ) { float_t s; float_t c; sincos256_pd(v, (__m256*)&s, (__m256*)&c) ; return s/c; } - // inline float_t log( const float_t& v ) { return log256_ps(v) ; } // inline float_t exp( const float_t& v ) { return exp256_ps(v) ; } inline float_t select(const float_t& mask, const float_t& a, const float_t& b ) { return _mm256_blendv_pd( b, a, mask ); } inline float_t select(const bool& mask , const float_t& a, const float_t& b ) { return mask ? a : b; } + inline float_t sign ( const float_t& v){ return select( v > 0., +1., -1. ); } inline float_t atan2( const float_t& y, const float_t& x ){ std::array bx{x.to_array()}, by{y.to_array()}; return float_t ( @@ -77,12 +76,51 @@ namespace AmpGen { { return _mm256_i64gather_pd(base_addr, double_to_int(offsets),sizeof(double)); } - stl_fallback( log ) + + inline void frexp(const AVX2d::float_t& value, AVX2d::float_t& mant, AVX2d::float_t& exponent) + { + auto arg_as_int = _mm256_castpd_si256(value); + static const AVX2d::float_t offset(4503599627370496.0 + 1022.0); // 2^52 + 1022.0 + static const __m256i pow2_52_i = _mm256_set1_epi64x(0x4330000000000000); // *reinterpret_cast(&pow2_52_d); + auto b = _mm256_srl_epi64(arg_as_int, _mm_cvtsi32_si128(52)); + auto c = _mm256_or_si256( b , pow2_52_i); + exponent = AVX2d::float_t( _mm256_castsi256_pd(c) ) - offset; + mant = _mm256_castsi256_pd(_mm256_or_si256(_mm256_and_si256 (arg_as_int, _mm256_set1_epi64x(0x000FFFFFFFFFFFFFll) ), _mm256_set1_epi64x(0x3FE0000000000000ll))); + } + + inline float_t fmadd( const float_t& a, const float_t& b, const float_t& c ) + { + return _mm256_fmadd_pd(a, b, c); + } + inline float_t log(const AVX2d::float_t& arg) + { + static const AVX2d::float_t corr = 0.693147180559945286226764; + static const AVX2d::float_t CL15 = 0.148197055177935105296783; + static const AVX2d::float_t CL13 = 0.153108178020442575739679; + static const AVX2d::float_t CL11 = 0.181837339521549679055568; + static const AVX2d::float_t CL9 = 0.22222194152736701733275; + static const AVX2d::float_t CL7 = 0.285714288030134544449368; + static const AVX2d::float_t CL5 = 0.399999999989941956712869; + static const AVX2d::float_t CL3 = 0.666666666666685503450651; + static const AVX2d::float_t CL1 = 2.0; + AVX2d::float_t mant, exponent; + frexp(arg, mant, exponent); + auto x = (mant - 1.) / (mant + 1.); + auto x2 = x * x; + auto p = fmadd(CL15, x2, CL13); + p = fmadd(p, x2, CL11); + p = fmadd(p, x2, CL9); + p = fmadd(p, x2, CL7); + p = fmadd(p, x2, CL5); + p = fmadd(p, x2, CL3); + p = fmadd(p, x2, CL1); + p = fmadd(p, x, corr * exponent); + return p; + } stl_fallback( exp ) stl_fallback( tan ) stl_fallback( sin ) stl_fallback( cos ) - inline float_t remainder( const float_t& a, const float_t& b ){ return a - _mm256_round_pd(a/b, _MM_FROUND_TO_NEG_INF) * b; } inline float_t fmod( const float_t& a, const float_t& b ) { @@ -149,15 +187,15 @@ namespace AmpGen { inline complex_t exp( const complex_t& v ){ return exp( v.re) * complex_t( cos( v.im ), sin( v.im ) ); } - inline float_t fmadd( const float_t& a, const float_t& b, const float_t& c ) - { - return _mm256_fmadd_pd(a, b, c ); - } inline complex_t sqrt( const complex_t& v ) { auto r = abs(v); - return complex_t ( sqrt( 0.5 * (r + v.re) ), sqrt( 0.5*( r - v.re ) ) ); + return complex_t ( sqrt( 0.5 * (r + v.re) ), sign(v.im) * sqrt( 0.5*( r - v.re ) ) ); } + inline complex_t log( const complex_t& v ) + { + return complex_t( log( v.re ) , atan2(v.im, v.re) ); + } inline std::ostream& operator<<( std::ostream& os, const complex_t& obj ) { return os << "( "<< obj.re << ") (" << obj.im << ")"; } #pragma omp declare reduction(+: float_t: \ diff --git a/Standalone.cmake b/Standalone.cmake index ad04032760d..ec5f4dbc520 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -13,7 +13,7 @@ if( NOT "${CMAKE_CXX_STANDARD}" ) endif() SET(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") -SET(ENABLE_AVX2 FALSE CACHE BOOL "ENABLE_AVX2") +SET(ENABLE_AVX2 TRUE CACHE BOOL "ENABLE_AVX2") SET(PRECISION "DOUBLE" CACHE STRING "PRECISION") set(CMAKE_CXX_EXTENSIONS OFF) diff --git a/examples/FitterWithPolarisation.cpp b/examples/FitterWithPolarisation.cpp index 69b39fd171f..4e0abc26d69 100644 --- a/examples/FitterWithPolarisation.cpp +++ b/examples/FitterWithPolarisation.cpp @@ -58,7 +58,7 @@ int main( int argc, char* argv[] ) std::string dataFile = NamedParameter("DataSample", "" , "Name of file containing data sample to fit." ); std::string logFile = NamedParameter("LogFile" , "Fitter.log", "Name of the output log file"); std::string plotFile = NamedParameter("Plots" , "plots.root", "Name of the output plot file"); - + std::string simFile = NamedParameter("SgIntegratorFname", "" , "Name of file containing simulated sample for using in MC integration"); auto bNames = NamedParameter("Branches", std::vector() ,"List of branch names, assumed to be \033[3m daughter1_px ... daughter1_E, daughter2_px ... \033[0m" ).getVector(); @@ -68,7 +68,7 @@ int main( int argc, char* argv[] ) if( dataFile == "" ) FATAL("Must specify input with option " << italic_on << "DataSample" << italic_off ); if( pNames.size() == 0 ) FATAL("Must specify event type with option " << italic_on << " EventType" << italic_off); - size_t seed = NamedParameter ("Seed" , 0 , "Random seed used" ); + size_t seed = NamedParameter ("Seed" , 1 , "Random seed used" ); TRandom3 rndm; rndm.SetSeed( seed ); @@ -87,7 +87,7 @@ int main( int argc, char* argv[] ) the parsed options. For historical reasons, this is referred to as loading it from a "Stream" */ MinuitParameterSet MPS; MPS.loadFromStream(); - for( auto& p : MPS ) if( p->flag() == Flag::Free ) p->setResult( gRandom->Gaus( p->mean(), p->err() ), p->err(), 0,0 ); + // for( auto& p : MPS ) if( p->flag() == Flag::Free ) p->setResult( gRandom->Gaus( p->mean(), p->err() ), p->err(), 0,0 ); /* An EventType specifies the initial and final state particles as a vector that will be described by the fit. It is typically loaded from the interface parameter EventType. */ @@ -108,7 +108,7 @@ int main( int argc, char* argv[] ) /* Generate events to normalise the PDF with. This can also be loaded from a file, which will be the case when efficiency variations are included. Default number of normalisation events is 2 million. */ - EventList_type eventsMC = Generator<>(evtType, &rndm).generate(int(2e6)); + EventList_type eventsMC = simFile == "" ? EventList_type(Generator<>(evtType, &rndm).generate(int(3365617)) ) : EventList_type(simFile, evtType); sig.setMC( eventsMC ); @@ -146,16 +146,6 @@ FitResult* doFit( PDF&& pdf, EventList_type& data, EventList_type& mc, MinuitPar /* Make the plots for the different components in the PDF, i.e. the signal and backgrounds. The structure assumed the PDF is some SumPDF. */ -// unsigned int counter = 1; -// for_each(pdf.pdfs(), [&]( const auto& f ){ -// auto mc_plot3 = mc.makeDefaultProjections(WeightFunction(f.evaluator()), Prefix("Model_cat"+std::to_string(counter))); -// for( auto& plot : mc_plot3 ) -// { -// plot->Scale( ( data.integral() * f.getWeight() ) / plot->Integral() ); -// plot->Write(); -// } -// counter++; -// } ); /* Estimate the chi2 using an adaptive / decision tree based binning, down to a minimum bin population of 15, and add it to the output. */ // Chi2Estimator chi2( data, mc, pdf, 15 ); @@ -172,11 +162,11 @@ FitResult* doFit( PDF&& pdf, EventList_type& data, EventList_type& mc, MinuitPar /* Write out the data plots. This also shows the first example of the named arguments to functions, emulating python's behaviour in this area */ - + auto evaluator_per_component = std::get<0>( pdf.pdfs() ).componentEvaluator(); for( const auto& proj : projections ) { proj(mc, evaluator, PlotOptions::Norm(data.size()), PlotOptions::AutoWrite() ); - //proj(mc, evaluator_per_component, PlotOptions::Prefix("amp"), PlotOptions::Norm(data.size()), PlotOptions::AutoWrite() ); + proj(mc, evaluator_per_component, PlotOptions::Prefix("amp"), PlotOptions::Norm(data.size()), PlotOptions::AutoWrite() ); proj(data, PlotOptions::Prefix("Data") )->Write(); } fr->print(); diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index 98b66bcd496..b7a3a10e452 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -125,7 +125,7 @@ std::complex Coupling::operator()() const Expression Coupling::to_expression() const { - return m_expr != nullptr ? m_expr->expression() : ( m_isCartesian ? Parameter(m_re->name()) + 1i * Parameter(m_im->name()) : Parameter( m_re->name() ) * fcn::exp( 1i * m_sf * Parameter(m_im->name()) ) ); + return m_expr != nullptr ? m_expr->expression() : ( m_isCartesian ? ComplexParameter(Parameter(m_re->name()), Parameter(m_im->name())) : Parameter( m_re->name() ) * fcn::exp( 1i * m_sf * Parameter(m_im->name()) ) ); } std::complex TotalCoupling::operator()() const diff --git a/src/BinaryExpression.cpp b/src/BinaryExpression.cpp index f249e3bbdd9..fdd516580d4 100644 --- a/src/BinaryExpression.cpp +++ b/src/BinaryExpression.cpp @@ -36,10 +36,13 @@ complex_t Fmod::operator()() const { return 0; } complex_t Equal::operator()() const { return lval() == rval() ; } complex_t ATan2::operator()() const { return atan2( std::real(lval() ), std::real(rval() ) ); } -std::string Sum::to_string(const ASTResolver* resolver) const { +std::string Sum::to_string(const ASTResolver* resolver) const +{ return lval.to_string(resolver) + " + " + rval.to_string(resolver) ; } -std::string Sub::to_string(const ASTResolver* resolver) const { + +std::string Sub::to_string(const ASTResolver* resolver) const +{ return lval.to_string(resolver) + "-" + bracketed( rval, [](auto& expression){ return is(expression) || is(expression) ; } , resolver ) ; } std::string Equal::to_string(const ASTResolver* resolver) const { return "(" + lval.to_string(resolver) + " == "+ rval.to_string(resolver) +")"; } diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 910b3c73711..60c7d6f0a62 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -98,15 +98,12 @@ void CoherentSum::prepare() void CoherentSum::updateNorms() { - std::vector cacheIndex; - std::transform( m_matrixElements.begin(), m_matrixElements.end(), std::back_inserter(cacheIndex), - [this](auto& m){ return this->m_integrator.getCacheIndex( m ) ; } ); if(std::any_of(m_matrixElements.begin(),m_matrixElements.end(), [](auto& me){ return me.workToDo; } )) { for ( unsigned i = 0; i != m_matrixElements.size(); ++i ) for ( size_t j = i; j < size(); ++j ){ if( m_matrixElements[i].workToDo || m_matrixElements[j].workToDo ) - m_integrator.queueIntegral( cacheIndex[i], cacheIndex[j] ,i, j, &m_normalisations ); + m_normalisations.get(i, j, &m_integrator, i, j); } } m_integrator.flush(); @@ -294,10 +291,9 @@ real_t CoherentSum::norm(const Bilinears& norms) const complex_t acc(0, 0); for ( size_t i = 0; i < size(); ++i ) { for ( size_t j = 0; j < size(); ++j ) { - auto val = norms.get(i, j) - * m_matrixElements[i].coefficient - * std::conj(m_matrixElements[j].coefficient); - acc += val; + acc += m_matrixElements[i].coefficient + * std::conj(m_matrixElements[j].coefficient) + * ( i > j ? std::conj(norm(j,i)) : norm(i,j) ); } } return acc.real(); @@ -372,27 +368,24 @@ std::function CoherentSum::evaluator(const EventList_type* return arrayToFunctor(values); } -KeyedView CoherentSum::componentEvaluator(const EventList_type* ievents) const +KeyedFunctors CoherentSum::componentEvaluator(const EventList_type* ievents) const { - auto events = ievents == nullptr ? m_integrator.events() : ievents; - - KeyedView rt(*events, m_matrixElements.size() ); + auto& cache = m_integrator.cache(); + KeyedFunctors rt; for( unsigned i = 0 ; i != m_matrixElements.size(); ++i ) { - auto& me = m_matrixElements[i]; - rt.setKey(i, programatic_name( me.decayTree.decayDescriptor() ) ); - #ifdef _OPENMP - #pragma omp parallel for - #endif - for( unsigned evt = 0 ; evt < events->size(); ++evt ) - { - complex_t total = 0; - for( unsigned j = 0 ; j != m_matrixElements.size(); ++j ){ - total += this->m_integrator.get(i, evt) * m_matrixElements[i].coefficient - * std::conj( this->m_integrator.get(j, evt) * m_matrixElements[j].coefficient ); - } - rt(events->at(evt), i) = m_weight * std::real( total ) / m_norm; + for( unsigned j = i ; j != m_matrixElements.size(); ++j ){ + auto mi = m_matrixElements[i]; + auto mj = m_matrixElements[j]; + auto ci = this->m_matrixElements[i].coefficient; + auto cj = this->m_matrixElements[j].coefficient; + double s = (i==j) ? 1 : 2 ; + auto name = programatic_name(mi.decayTree.decayDescriptor()) + "_" + programatic_name( mj.decayTree.decayDescriptor() ); + INFO("Adding evaluator for: " << name ); + auto functor = [ci,cj,i,j,s, &cache](const Event& event){ return s * std::real( ci * cache.get( event.index(), i ) * std::conj( cj * cache.get( event.index(), j ) ) ) ;}; + rt.add(functor, name, ""); } } + INFO(" Returning: " << rt.keys.size() << " functors" ); return rt; } diff --git a/src/Expression.cpp b/src/Expression.cpp index 058ee0d342a..9433ef4c9cf 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -25,6 +25,7 @@ DEFINE_CAST(Parameter ) DEFINE_CAST(SubTree ) DEFINE_CAST(Ternary ) DEFINE_CAST(Function ) +DEFINE_CAST(ComplexParameter); Expression::Expression( const std::shared_ptr& expression ) : m_expression( expression ) {} @@ -324,3 +325,25 @@ Expression AmpGen::fcn::fpow( const Expression& x, const int& n){ for( int y=0;yenableCuda() ) complex_type = "AmpGen::CUDA::complex_t"; + if( resolver != nullptr && resolver->enableAVX() ) complex_type = "AmpGen::AVX2d::complex_t"; + return complex_type + "(" + m_real.to_string(resolver) + ", " + m_imag.to_string(resolver) +")"; +} + +void ComplexParameter::resolve( ASTResolver& resolver ) const +{ + m_real.resolve(resolver); + m_imag.resolve(resolver); +} + +complex_t ComplexParameter::operator()() const +{ + return m_real() + 1i * m_imag(); +} diff --git a/src/Integrator.cpp b/src/Integrator.cpp index 531248a016b..4632a44b764 100644 --- a/src/Integrator.cpp +++ b/src/Integrator.cpp @@ -37,7 +37,7 @@ void Bilinears::resize( const size_t& r, const size_t& c) void Integrator::integrateBlock() { #pragma omp parallel for - for ( size_t roll = 0; roll < N; ++roll ) { + for ( size_t roll = 0; roll < m_counter; ++roll ) { float_v re( 0.f ); float_v im( 0.f ); auto b1 = m_cache.data() + m_integrals[roll].i * m_cache.nBlocks(); @@ -45,43 +45,24 @@ void Integrator::integrateBlock() for ( size_t i = 0; i < m_cache.nBlocks(); ++i ) { auto c = b1[i] * conj(b2[i]); #if ENABLE_AVX2 - re = fmadd(re, m_weight[i], real(c) ); - im = fmadd(im, m_weight[i], imag(c) ); + re = fmadd( m_weight[i], real(c), re ); + im = fmadd( m_weight[i], imag(c), im ); #else re = re + m_weight[i] * real(c); im = im + m_weight[i] * imag(c); #endif } - m_integrals[roll].transfer( utils::sum_elements( complex_v(re, im) ) / m_norm ); + *m_integrals[roll].result = utils::sum_elements( complex_v(re, im) ) / m_norm; } m_counter = 0; } bool Integrator::isReady() const { return m_events != nullptr; } -void Integrator::queueIntegral(const size_t& c1, - const size_t& c2, - const size_t& i, - const size_t& j, - Bilinears* out, - const bool& sim) +void Integrator::queueIntegral(complex_t* result, const unsigned& i, const unsigned& j) { - if( !out->workToDo(i,j) ) return; - if( sim ) - addIntegralKeyed( c1, c2, [out,i,j]( const complex_t& val ){ out->set(i,j,val); if( i != j ) out->set(j,i, std::conj(val) ); } ); - else - addIntegralKeyed( c1, c2, [out,i,j]( const complex_t& val ){ out->set(i,j,val); } ); -} - -void Integrator::addIntegralKeyed( const size_t& c1, const size_t& c2, const TransferFCN& tFunc ) -{ - m_integrals[m_counter++] = Integral(c1,c2,tFunc); - if ( m_counter == N ) integrateBlock(); -} - -void Integrator::queueIntegral(const size_t& i, const size_t& j, complex_t* result) -{ - addIntegralKeyed(i, j, [result](const complex_t& val){ *result = val ; } ); + m_integrals[m_counter++] = QueuedIntegral(result, i, j ); + if( m_counter == N ) integrateBlock(); } void Integrator::flush() diff --git a/src/Minimiser.cpp b/src/Minimiser.cpp index 3c7f326fad8..0eaabb29f01 100644 --- a/src/Minimiser.cpp +++ b/src/Minimiser.cpp @@ -17,6 +17,7 @@ #include "Math/Factory.h" #include "Math/Functor.h" #include "Math/Minimizer.h" +#include "AmpGen/ProfileClock.h" using namespace AmpGen; using namespace ROOT; @@ -25,11 +26,13 @@ unsigned int Minimiser::nPars() const { return m_nParams; } double Minimiser::operator()( const double* xx ) { + ProfileClock callTime; for(size_t i = 0; i < m_mapping.size(); ++i ) { m_parSet->at( m_mapping[i] )->setCurrentFitVal( xx[i] ); } double LL = m_theFunction() ; for ( auto& extendTerm : m_extendedTerms ) LL -= 2 * extendTerm->getVal(); + callTime.stop(); return LL - m_ll_zero; } diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index ba4c1cf10e0..bc0e5df0654 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -34,6 +34,8 @@ using namespace AmpGen; using namespace std::complex_literals; +// ENABLE_DEBUG( PolarisedSum ) + namespace AmpGen { make_enum(spaceType, spin, flavour) } std::vector convertProxies(const std::vector& proxyVector, const std::function& transform) @@ -125,9 +127,7 @@ PolarisedSum::PolarisedSum(const EventType& type, DebugSymbols db; auto prob = probExpression(transitionMatrix(), convertProxies(m_pVector,[](auto& p){ return Parameter(p->name());} ), m_debug ? &db : nullptr); - m_probExpression = CompiledExpression(prob, "prob_unnormalised", {}, db, m_mps); - CompilerWrapper().compile(m_probExpression); - m_probExpression.prepare(); + m_probExpression = make_expression( prob, "prob_unnormalised", *m_mps ); } std::vector PolarisedSum::polarisations( const std::string& name ) const @@ -190,41 +190,27 @@ std::vector> PolarisedSum::matrixElements() const return m_matrixElements; } + void PolarisedSum::prepare() { - DEBUG( "Preparing: " << m_prefix << " " << m_events << " ready = " << m_integrator.isReady() ); + auto resetFlags = [](auto& t){ t.workToDo = false; t.resetExternals() ; }; + auto flagUpdate = [this](auto& t){ t.workToDo = this->m_nCalls == 0 || t.hasExternalsChanged(); }; + auto updateData = [this](auto& t) mutable { if( t.workToDo && this->m_events != nullptr ) this->m_cache.update(this->m_events->store(), t) ; }; + auto updateInteg = [this](auto& t) mutable { if( t.workToDo ) this->m_integrator.updateCache(t) ; }; + transferParameters(); - ProfileClock tEval; - size_t size_of = size() / m_matrixElements.size(); - for(auto& t : m_matrixElements){ - if( m_nCalls != 0 && !t.hasExternalsChanged() ) continue; - if( m_events != nullptr ) m_cache.update(m_events->store(), t); - m_integrator.updateCache(t); - t.resetExternals(); - t.workToDo = true; - } - tEval.stop(); - ProfileClock tIntegral; - m_rho = densityMatrix(m_dim.first, m_pVector); + for_each_sequence(m_matrixElements.begin(), m_matrixElements.end(), flagUpdate, updateData, updateInteg); if( m_integrator.isReady() ) updateNorms(); - tIntegral.stop(); - if( m_verbosity && m_nCalls % 100 == 0 ){ - INFO("Time to evaluate = " << tEval << " ms; " << "norm = " << tIntegral << " ms; "); - } -// debug_norm(); - m_nCalls++; - for( auto& me : m_matrixElements ) me.workToDo = false; - auto pw = m_weight / m_norm; - #pragma omp parallel for - for( unsigned block = 0 ; block < m_events->nBlocks(); ++block ) - m_pdfCache[block] = pw * m_probExpression(&m_cache(block, 0)); - - DEBUG( "m_pdfCache[0] = " << m_pdfCache[0] << " w/o caching = " << pw * getValNoCache(m_events->at(0)) ); + std::for_each( m_matrixElements.begin(), m_matrixElements.end(), resetFlags ); + if( m_nCalls % 10000 == 0 ) debug_norm(); + DEBUG( "m_pdfCache[0] = " << m_pdfCache[0] << " w/o caching = " << (m_weight/m_norm) * getValNoCache(m_events->at(0))); + m_pdfCache.update(m_cache, m_probExpression); + m_nCalls++; } float_v PolarisedSum::operator()( const float_v*, const unsigned index ) const { - return m_pdfCache[index]; + return ( m_weight / m_norm ) * m_pdfCache[index]; } void PolarisedSum::debug_norm() @@ -232,11 +218,8 @@ void PolarisedSum::debug_norm() double norm_slow = 0; for( auto& evt : *m_integrator.events() ) norm_slow += evt.weight() * getValNoCache(evt) / evt.genPdf(); - INFO("Norm : " << std::setprecision(10) - << "bilinears=" << m_norm - << "; exact=" << norm_slow / m_integrator.norm() - << "; d = " << m_norm - norm_slow / m_integrator.norm() - << "; sample=" << m_integrator.norm() ); + norm_slow /= m_integrator.norm(); + INFO("Norm: " << std::setprecision(10) << "bilinears=" << m_norm << "; Slow=" << norm_slow << "; d = " << m_norm - norm_slow); } void PolarisedSum::setEvents( EventList_type& events ) @@ -244,8 +227,8 @@ void PolarisedSum::setEvents( EventList_type& events ) reset(); if( m_events != nullptr && m_ownEvents ) delete m_events; m_events = &events; - m_cache = Store(m_events->size(), m_matrixElements, m_dim.first * m_dim.second ); - m_pdfCache.resize( m_events->nBlocks() ); + m_cache = Store(m_events->size(), m_matrixElements, m_dim.first * m_dim.second ); + m_pdfCache = Store(m_events->size(), m_probExpression ); } void PolarisedSum::setMC( EventList_type& events ) @@ -322,7 +305,7 @@ void PolarisedSum::updateNorms() complex_t z = 0; for(size_t i = 0; i < m_matrixElements.size(); ++i){ for(size_t j = 0; j < m_matrixElements.size(); ++j){ - z += m_matrixElements[i].coupling()*std::conj(m_matrixElements[j].coupling())* ( i > j ? std::conj(norm(j,i)) : norm(i,j) ); + z += m_matrixElements[i].coupling()*std::conj(m_matrixElements[j].coupling()) * ( i > j ? std::conj(norm(j,i)) : norm(i,j) ); } } m_norm = std::real(z); @@ -461,13 +444,14 @@ std::vector PolarisedSum::fitFractions(const LinearErrorPropagator& void PolarisedSum::transferParameters() { - if( m_probExpression.isLinked() ) m_probExpression.prepare(); + m_probExpression.prepare(); for(auto& me : m_matrixElements){ me.coefficient = me.coupling(); me.prepare(); } - for(auto& p : m_pVector ) p.update(); + for(auto& p : m_pVector) p.update(); m_weight.update(); + m_rho = densityMatrix(m_dim.first, m_pVector); } real_t PolarisedSum::getValNoCache( const Event& evt ) const @@ -487,7 +471,7 @@ double PolarisedSum::getWeight() const { return m_weight ; } std::function PolarisedSum::evaluator(const EventList_type* ievents) const { auto events = ievents == nullptr ? m_integrator.events() : ievents; - Store store( events->size(), m_matrixElements); + Store store(events->size(), m_matrixElements, m_dim.first * m_dim.second); for( auto& me : m_matrixElements ) store.update(events->store(), me ); std::vector values( events->aligned_size() ); @@ -503,38 +487,37 @@ std::function PolarisedSum::evaluator(const EventList_type return arrayToFunctor(values); } -KeyedView PolarisedSum::componentEvaluator(const EventList_type* events) const +KeyedFunctors PolarisedSum::componentEvaluator(const EventList_type* events) const { - KeyedView rt(*events, m_matrixElements.size() ); -// std::vector address_mapping(m_matrixElements.size()); -// for( unsigned i = 0; i != m_matrixElements.size(); ++i ) -// address_mapping[i] = m_integrator.getCacheIndex( m_matrixElements[i].amp ); -// -// for( unsigned i = 0 ; i != m_matrixElements.size(); ++i ) -// { -// auto& me = m_matrixElements[i]; -// rt.setKey(i, programatic_name( me.decayTree.decayDescriptor() ) ); -// #ifdef _OPENMP -// #pragma omp parallel for -// #endif -// for( unsigned evt = 0 ; evt != m_integrator.events()->size(); ++evt ) -// { -// complex_t total = 0; -// for( unsigned j = 0 ; j != m_matrixElements.size(); ++j ){ -// for( unsigned x = 0; x != m_norms.size(); ++x ) -// { -// auto s1 = m_dim.first; -// auto s2 = m_dim.second; -// auto f = x % s2; -// auto psiIndex = (x-f) / s2; -// auto m2 = psiIndex % s1; -// auto m1 = (psiIndex-m2)/s1; -// total += m_rho[psiIndex] * this->m_integrator.get( address_mapping[i] + m1 * s2 + f, evt ) * m_matrixElements[i].coefficient -// * std::conj( this->m_integrator.get( address_mapping[j] + m2 * s2 + f, evt ) * m_matrixElements[j].coefficient ); -// } -// } -// rt(events->at(evt), i) = m_weight * std::real( total ) / m_norm; -// } -// } + auto& cache = m_integrator.cache(); + KeyedFunctors rt; + for( unsigned i = 0 ; i != m_matrixElements.size(); ++i ) + { + for( unsigned j = i ; j != m_matrixElements.size(); ++j ){ + auto mi = m_matrixElements[i]; + auto mj = m_matrixElements[j]; + auto ci = this->m_matrixElements[i].coefficient; + auto cj = this->m_matrixElements[j].coefficient; + double s = (i==j) ? 1 : 2 ; + auto name = programatic_name(mi.decayTree.decayDescriptor()) + "_" + programatic_name( mj.decayTree.decayDescriptor() ); + INFO("Adding evaluator for: " << name ); + auto functor = [ci,cj,i,j,s, &cache, this](const Event& event){ + auto [s1,s2] = this->m_dim; + auto R = s1 * s2; + complex_t total = 0; + for( unsigned x = 0; x != this->m_norms.size(); ++x ) + { + auto f = x % s2; + auto psiIndex = (x-f) / s2; + auto m2 = psiIndex % s1; + auto m1 = (psiIndex-m2)/s1; + total += this->m_rho[psiIndex] * ci * cache.get(event.index(),R * i + m1 * s2 + f) + * std::conj( cj * cache.get(event.index(),R * j + m2 * s2 + f) ); + } + return s * std::real(total); + }; + rt.add(functor, name, ""); + } + } return rt; } diff --git a/src/Projection.cpp b/src/Projection.cpp index 2afa383fc4f..89b354a7d89 100644 --- a/src/Projection.cpp +++ b/src/Projection.cpp @@ -76,22 +76,22 @@ template <> TH1D* Projection::projInternal( const EventList& events, const Argum return events.makeProjection(*this, args); } -template <> std::tuple, THStack*> Projection::projInternal(const EventList& events, const KeyedView& weightFunction, const ArgumentPack& args) const +template <> std::tuple, THStack*> Projection::projInternal(const EventList& events, const Projection::keyedFunctors& weightFunction, const ArgumentPack& args) const { std::vector hists; double norm_sum = args.getArg(1).val; std::string prefix = args.getArg().val; bool autowrite = args.get() != nullptr; THStack* stack = args.getArg(new THStack()).val; - if( prefix != "" ) prefix = prefix +"_"; - for( unsigned int i = 0 ; i != weightFunction.width(); ++i ) - hists.push_back( plot(prefix + weightFunction.key(i)==""?"C"+std::to_string(i):weightFunction.key(i)) ); auto selection = args.getArg().val; + if( prefix != "" ) prefix = prefix +"_"; + for( auto& key : weightFunction.keys ) + hists.push_back( plot(prefix + key ) ); for( const auto& evt : events ){ if( selection != nullptr && !selection(evt) ) continue; auto pos = operator()(evt); auto weights = weightFunction(evt); - for( unsigned j = 0 ; j != weightFunction.width(); ++j ) hists[j]->Fill( pos, evt.weight() * weights[j] / evt.genPdf() ); + for( unsigned j = 0 ; j != weights.size(); ++j ) hists[j]->Fill( pos, evt.weight() * weights[j] / evt.genPdf() ); } std::sort( std::begin(hists), std::end(hists), [](auto& h1, auto& h2){ return h1->Integral() < h2->Integral() ; } ); double total = std::accumulate( std::begin(hists), std::end(hists), 0.0, [](double& t, auto& h){ return t + h->Integral() ; } ); @@ -112,22 +112,22 @@ template <> TH1D* Projection::projInternal( const EventListSIMD& events, const A return events.makeProjection(*this, args); } -template <> std::tuple, THStack*> Projection::projInternal(const EventListSIMD& events, const KeyedView& weightFunction, const ArgumentPack& args) const +template <> std::tuple, THStack*> Projection::projInternal(const EventListSIMD& events, const Projection::keyedFunctors& weightFunction, const ArgumentPack& args) const { std::vector hists; double norm_sum = args.getArg(1).val; std::string prefix = args.getArg().val; bool autowrite = args.get() != nullptr; THStack* stack = args.getArg(new THStack()).val; - if( prefix != "" ) prefix = prefix +"_"; - for( unsigned int i = 0 ; i != weightFunction.width(); ++i ) - hists.push_back( plot(prefix + weightFunction.key(i)==""?"C"+std::to_string(i):weightFunction.key(i)) ); auto selection = args.getArg().val; + if( prefix != "" ) prefix = prefix +"_"; + for( auto& key : weightFunction.keys ) + hists.push_back( plot(prefix + key ) ); for( const auto& evt : events ){ if( selection != nullptr && !selection(evt) ) continue; auto pos = operator()(evt); auto weights = weightFunction(evt); - for( unsigned j = 0 ; j != weightFunction.width(); ++j ) hists[j]->Fill( pos, evt.weight() * weights[j] / evt.genPdf() ); + for( unsigned j = 0 ; j != weights.size(); ++j ) hists[j]->Fill( pos, evt.weight() * weights[j] / evt.genPdf() ); } std::sort( std::begin(hists), std::end(hists), [](auto& h1, auto& h2){ return h1->Integral() < h2->Integral() ; } ); double total = std::accumulate( std::begin(hists), std::end(hists), 0.0, [](double& t, auto& h){ return t + h->Integral() ; } ); diff --git a/test/test_avx2d.cpp b/test/test_avx2d.cpp index 20119f426e8..f914bf28790 100644 --- a/test/test_avx2d.cpp +++ b/test/test_avx2d.cpp @@ -12,6 +12,16 @@ namespace utf = boost::unit_test; using namespace AmpGen; +BOOST_AUTO_TEST_CASE( test_log ) +{ + AVX2d::float_t p(0.3, 0.5, 10.0, 7.0); + auto logged = AVX2d::log( p ).to_array() ; + BOOST_TEST( logged[0] == std::log(0.3), boost::test_tools::tolerance(1e-15 ) ); + BOOST_TEST( logged[1] == std::log(0.5), boost::test_tools::tolerance(1e-15 ) ); + BOOST_TEST( logged[2] == std::log(10.0), boost::test_tools::tolerance(1e-15 ) ); + BOOST_TEST( logged[3] == std::log(7.0), boost::test_tools::tolerance(1e-15 ) ); +} + BOOST_AUTO_TEST_CASE( test_fmod ) { std::vector a = {5.1, -5.1, 5.1, -5.1}; @@ -54,6 +64,8 @@ BOOST_AUTO_TEST_CASE( test_gather ) BOOST_TEST( v[3] == data[3] ); } + + #else BOOST_AUTO_TEST_CASE( test_dummy ) { From 33121a55aeb2c687f8f2e6dfb93681c5865910a3 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 19 Apr 2020 14:55:22 +0200 Subject: [PATCH 171/250] fix travis... --- .ci/build_root_linux.sh | 1 + README.md | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.ci/build_root_linux.sh b/.ci/build_root_linux.sh index fd12bdea9b6..adc3f336000 100755 --- a/.ci/build_root_linux.sh +++ b/.ci/build_root_linux.sh @@ -6,6 +6,7 @@ export PATH="$DEPS_DIR/miniconda/bin:$PATH" hash -r conda config --add channels conda-forge conda install --quiet --yes -c conda-forge/label/gcc8 root +conda config --set channel_priority strict source "$DEPS_DIR/miniconda/bin/thisroot.sh" export CXX="$DEPS_DIR/miniconda/bin/g++" diff --git a/README.md b/README.md index 9dd1f285f52..a862c53b3d2 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,8 @@ There is at the time of writing only a master branch (FIXME) ##### Build requirements: * cmake >= 3.11.0 -* C++ compiler with CXX standard >= 14 (gcc >= 4.9.3, clang ~ 5). - Defaults to Cxx17 (enable cxx14 with cmake flag `-DCMAKE_CXX_STANDARD=14` ) +* C++ compiler with CXX standard >= 17 (gcc >= 8) + Defaults to Cxx17 * ROOT >= 6 with MathMore To (re)configure root with these options, use the additional command line options `-Dcxx14 -Dmathmore=ON` when configuring the installation of ROOT. @@ -38,7 +38,7 @@ There is at the time of writing only a master branch (FIXME) * xROOTd for network file access * OpenMP for multithreading * ROOT >= 6 with MathMore and Minuit2 enabled. The external version of Minuit2 provided as an external package of GooFit is used if the ROOT version is not unavailable. - To (re)configure root with these options, use the additional command line options `-Dcxx14 -Dminuit2=ON -Dmathmore=ON` when configuring the installation of ROOT. + To (re)configure root with these options, use the additional command line options `-Dminuit2=ON -Dmathmore=ON` when configuring the installation of ROOT. #### Building The configuration of the AmpGen build is performed by cmake. From b97eceba23c755822d560a54c647b239fe7c5e61 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 19 Apr 2020 15:16:05 +0200 Subject: [PATCH 172/250] fix travis... --- .ci/build_root_linux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/build_root_linux.sh b/.ci/build_root_linux.sh index adc3f336000..31994e26076 100755 --- a/.ci/build_root_linux.sh +++ b/.ci/build_root_linux.sh @@ -5,8 +5,8 @@ bash miniconda.sh -b -p $DEPS_DIR/miniconda export PATH="$DEPS_DIR/miniconda/bin:$PATH" hash -r conda config --add channels conda-forge -conda install --quiet --yes -c conda-forge/label/gcc8 root conda config --set channel_priority strict +conda install --quiet --yes -c conda-forge/label/gcc8 root zstd source "$DEPS_DIR/miniconda/bin/thisroot.sh" export CXX="$DEPS_DIR/miniconda/bin/g++" From f1b159152c920bbfa906e8815185910167143cb4 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 19 Apr 2020 15:37:22 +0200 Subject: [PATCH 173/250] fix travis... --- .ci/build_root_linux.sh | 7 ++++--- .ci/travis_linux.sh | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.ci/build_root_linux.sh b/.ci/build_root_linux.sh index 31994e26076..551e2c512e1 100755 --- a/.ci/build_root_linux.sh +++ b/.ci/build_root_linux.sh @@ -6,8 +6,9 @@ export PATH="$DEPS_DIR/miniconda/bin:$PATH" hash -r conda config --add channels conda-forge conda config --set channel_priority strict -conda install --quiet --yes -c conda-forge/label/gcc8 root zstd +# conda install --quiet --yes -c conda-forge/label/gcc8 root zstd +conda create -n my_root_env root -c conda-forge/label/gcc8 -source "$DEPS_DIR/miniconda/bin/thisroot.sh" -export CXX="$DEPS_DIR/miniconda/bin/g++" +# source "$DEPS_DIR/miniconda/bin/thisroot.sh" +# export CXX="$DEPS_DIR/miniconda/bin/g++" popd diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh index 9f29206a32a..df7bd9472ee 100644 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -5,6 +5,7 @@ set -evx mkdir -p build cd build +conda activate my_root_env cmake .. -DCMAKE_CXX_COMPILER=$CXX cmake --build . -- -j2 From e1f26c87970e8e9edd826477df917fa2b5680fc8 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 19 Apr 2020 15:43:45 +0200 Subject: [PATCH 174/250] fix travis... --- .ci/build_root_linux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/build_root_linux.sh b/.ci/build_root_linux.sh index 551e2c512e1..6eca271e9a0 100755 --- a/.ci/build_root_linux.sh +++ b/.ci/build_root_linux.sh @@ -7,7 +7,7 @@ hash -r conda config --add channels conda-forge conda config --set channel_priority strict # conda install --quiet --yes -c conda-forge/label/gcc8 root zstd -conda create -n my_root_env root -c conda-forge/label/gcc8 +conda create --quiet -n my_root_env root -c conda-forge/label/gcc8 # source "$DEPS_DIR/miniconda/bin/thisroot.sh" # export CXX="$DEPS_DIR/miniconda/bin/g++" From 194f473fba2c4541b8d7a95907ffe85910e27ab9 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 19 Apr 2020 15:55:27 +0200 Subject: [PATCH 175/250] fix travis... --- .ci/build_root_linux.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/build_root_linux.sh b/.ci/build_root_linux.sh index 6eca271e9a0..a1bfec49916 100755 --- a/.ci/build_root_linux.sh +++ b/.ci/build_root_linux.sh @@ -6,8 +6,8 @@ export PATH="$DEPS_DIR/miniconda/bin:$PATH" hash -r conda config --add channels conda-forge conda config --set channel_priority strict -# conda install --quiet --yes -c conda-forge/label/gcc8 root zstd -conda create --quiet -n my_root_env root -c conda-forge/label/gcc8 +# conda install --quiet --yes -c conda-forge/label/gcc8 root_base doxygen +conda create --quiet --yes -n my_root_env root doxygen -c conda-forge/label/gcc8 # source "$DEPS_DIR/miniconda/bin/thisroot.sh" # export CXX="$DEPS_DIR/miniconda/bin/g++" From 6403a294c2d7b00cf8a017432050afe96bc6d74e Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 19 Apr 2020 16:07:16 +0200 Subject: [PATCH 176/250] fix travis... --- .ci/build_root_linux.sh | 28 ++++++++++++++-------------- .ci/travis_linux.sh | 12 +++++++++++- .travis.yml | 22 +++++++++++----------- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/.ci/build_root_linux.sh b/.ci/build_root_linux.sh index a1bfec49916..dd6d15db351 100755 --- a/.ci/build_root_linux.sh +++ b/.ci/build_root_linux.sh @@ -1,14 +1,14 @@ -pushd $DEPS_DIR - -wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh -bash miniconda.sh -b -p $DEPS_DIR/miniconda -export PATH="$DEPS_DIR/miniconda/bin:$PATH" -hash -r -conda config --add channels conda-forge -conda config --set channel_priority strict -# conda install --quiet --yes -c conda-forge/label/gcc8 root_base doxygen -conda create --quiet --yes -n my_root_env root doxygen -c conda-forge/label/gcc8 - -# source "$DEPS_DIR/miniconda/bin/thisroot.sh" -# export CXX="$DEPS_DIR/miniconda/bin/g++" -popd +# pushd $DEPS_DIR +# +# wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh +# bash miniconda.sh -b -p $DEPS_DIR/miniconda +# export PATH="$DEPS_DIR/miniconda/bin:$PATH" +# hash -r +# conda config --add channels conda-forge +# conda config --set channel_priority strict +# # conda install --quiet --yes -c conda-forge/label/gcc8 root_base doxygen +# conda create --quiet --yes -n my_root_env root_base doxygen -c conda-forge/label/gcc8 +# +# # source "$DEPS_DIR/miniconda/bin/thisroot.sh" +# # export CXX="$DEPS_DIR/miniconda/bin/g++" +# popd diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh index df7bd9472ee..1e71238f1f0 100644 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -1,3 +1,14 @@ + +wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh +bash miniconda.sh -b -p $DEPS_DIR/miniconda +export PATH="$DEPS_DIR/miniconda/bin:$PATH" +hash -r +conda config --add channels conda-forge +conda config --set channel_priority strict +# conda install --quiet --yes -c conda-forge/label/gcc8 root_base doxygen +conda create --quiet --yes -n my_root_env root_base doxygen -c conda-forge/label/gcc8 +conda activate my_root_env + echo -en 'travis_fold:start:script.build\\r' echo "Building..." echo "Building under OS: $TRAVIS_OS_NAME, CXX =$CXX" @@ -5,7 +16,6 @@ set -evx mkdir -p build cd build -conda activate my_root_env cmake .. -DCMAKE_CXX_COMPILER=$CXX cmake --build . -- -j2 diff --git a/.travis.yml b/.travis.yml index 8dbf58565e3..13daca97f93 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,17 +10,17 @@ matrix: packages: - libomp - os: linux - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-8 - - doxygen - - doxygen-doc - - doxygen-gui - - graphviz - - libtbb-dev + # addons: + # apt: + # sources: + # - ubuntu-toolchain-r-test + # packages: + # - g++-8 + # - doxygen + # - doxygen-doc + # - doxygen-gui + # - graphviz + # - libtbb-dev env: - MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" From 1c7d80ffdad68bae2409f879c784330b7273a682 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 19 Apr 2020 16:17:26 +0200 Subject: [PATCH 177/250] fix travis... --- .ci/travis_linux.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh index 1e71238f1f0..ded5c34e9d0 100644 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -7,6 +7,7 @@ conda config --add channels conda-forge conda config --set channel_priority strict # conda install --quiet --yes -c conda-forge/label/gcc8 root_base doxygen conda create --quiet --yes -n my_root_env root_base doxygen -c conda-forge/label/gcc8 +conda init bash conda activate my_root_env echo -en 'travis_fold:start:script.build\\r' @@ -14,9 +15,11 @@ echo "Building..." echo "Building under OS: $TRAVIS_OS_NAME, CXX =$CXX" set -evx +# -DCMAKE_CXX_COMPILER=$CXX + mkdir -p build cd build -cmake .. -DCMAKE_CXX_COMPILER=$CXX +cmake .. cmake --build . -- -j2 set +evx From 7b9816dc5af2fb08609f56b8330e2e145adfd5a0 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 19 Apr 2020 16:28:32 +0200 Subject: [PATCH 178/250] fix travis... --- .ci/build_root_linux.sh | 28 ++++++++++++++-------------- .ci/travis_linux.sh | 17 ++++++++--------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/.ci/build_root_linux.sh b/.ci/build_root_linux.sh index dd6d15db351..0a4c760c7ac 100755 --- a/.ci/build_root_linux.sh +++ b/.ci/build_root_linux.sh @@ -1,14 +1,14 @@ -# pushd $DEPS_DIR -# -# wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh -# bash miniconda.sh -b -p $DEPS_DIR/miniconda -# export PATH="$DEPS_DIR/miniconda/bin:$PATH" -# hash -r -# conda config --add channels conda-forge -# conda config --set channel_priority strict -# # conda install --quiet --yes -c conda-forge/label/gcc8 root_base doxygen -# conda create --quiet --yes -n my_root_env root_base doxygen -c conda-forge/label/gcc8 -# -# # source "$DEPS_DIR/miniconda/bin/thisroot.sh" -# # export CXX="$DEPS_DIR/miniconda/bin/g++" -# popd +pushd $DEPS_DIR + +wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh +bash miniconda.sh -b -p $DEPS_DIR/miniconda +export PATH="$DEPS_DIR/miniconda/bin:$PATH" +hash -r +conda config --add channels conda-forge +conda config --set channel_priority strict +# conda install --quiet --yes -c conda-forge/label/gcc8 root_base doxygen +conda create --quiet --yes -n my_root_env root_base doxygen -c conda-forge/label/gcc8 +conda init bash +# source "$DEPS_DIR/miniconda/bin/thisroot.sh" +# export CXX="$DEPS_DIR/miniconda/bin/g++" +popd diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh index ded5c34e9d0..22690f6dd50 100644 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -1,13 +1,12 @@ -wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh -bash miniconda.sh -b -p $DEPS_DIR/miniconda -export PATH="$DEPS_DIR/miniconda/bin:$PATH" -hash -r -conda config --add channels conda-forge -conda config --set channel_priority strict -# conda install --quiet --yes -c conda-forge/label/gcc8 root_base doxygen -conda create --quiet --yes -n my_root_env root_base doxygen -c conda-forge/label/gcc8 -conda init bash +# wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh +# bash miniconda.sh -b -p $DEPS_DIR/miniconda +# export PATH="$DEPS_DIR/miniconda/bin:$PATH" +# hash -r +# conda config --add channels conda-forge +# conda config --set channel_priority strict +# # conda install --quiet --yes -c conda-forge/label/gcc8 root_base doxygen +# conda create --quiet --yes -n my_root_env root_base doxygen -c conda-forge/label/gcc8 conda activate my_root_env echo -en 'travis_fold:start:script.build\\r' From 9c7e191f8e3664b36000ceb8e0286246f2d94675 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 19 Apr 2020 16:34:05 +0200 Subject: [PATCH 179/250] fix travis... --- .ci/travis_linux.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh index 22690f6dd50..eb79ed00251 100644 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -7,6 +7,9 @@ # conda config --set channel_priority strict # # conda install --quiet --yes -c conda-forge/label/gcc8 root_base doxygen # conda create --quiet --yes -n my_root_env root_base doxygen -c conda-forge/label/gcc8 + +# from https://stackoverflow.com/questions/55342122/conda-activate-on-travis-ci +source $(conda info --root)/etc/profile.d/conda.sh conda activate my_root_env echo -en 'travis_fold:start:script.build\\r' From 77339caf4fe39c4f9a2a0500e1e98f160563cbc7 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 20 Apr 2020 10:47:59 +0200 Subject: [PATCH 180/250] fix travis build --- .ci/build_root.sh | 20 ++++++++++++++++++++ .ci/build_root_linux.sh | 12 +++++++++--- .ci/travis_linux.sh | 2 +- .travis.yml | 4 ++-- 4 files changed, 32 insertions(+), 6 deletions(-) create mode 100755 .ci/build_root.sh diff --git a/.ci/build_root.sh b/.ci/build_root.sh new file mode 100755 index 00000000000..6c184476362 --- /dev/null +++ b/.ci/build_root.sh @@ -0,0 +1,20 @@ +pushd $DEPS_DIR + +if [[ $1 == "osx" ]] ; then + wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh -O miniconda.sh +elif [[ $1 == "linux" ]] ; then + wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh +fi + +bash miniconda.sh -b -p $DEPS_DIR/miniconda +export PATH="$DEPS_DIR/miniconda/bin:$PATH" +hash -r +conda config --add channels conda-forge +conda config --set channel_priority strict + +# conda install --quiet --yes -c conda-forge/label/gcc8 root_base doxygen +conda create --quiet --yes -n my_root_env root doxygen zstd=1.3.7 -c conda-forge +# conda init bash +# source "$DEPS_DIR/miniconda/bin/thisroot.sh" +# export CXX="$DEPS_DIR/miniconda/bin/g++" +popd diff --git a/.ci/build_root_linux.sh b/.ci/build_root_linux.sh index 0a4c760c7ac..6c184476362 100755 --- a/.ci/build_root_linux.sh +++ b/.ci/build_root_linux.sh @@ -1,14 +1,20 @@ pushd $DEPS_DIR -wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh +if [[ $1 == "osx" ]] ; then + wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh -O miniconda.sh +elif [[ $1 == "linux" ]] ; then + wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh +fi + bash miniconda.sh -b -p $DEPS_DIR/miniconda export PATH="$DEPS_DIR/miniconda/bin:$PATH" hash -r conda config --add channels conda-forge conda config --set channel_priority strict + # conda install --quiet --yes -c conda-forge/label/gcc8 root_base doxygen -conda create --quiet --yes -n my_root_env root_base doxygen -c conda-forge/label/gcc8 -conda init bash +conda create --quiet --yes -n my_root_env root doxygen zstd=1.3.7 -c conda-forge +# conda init bash # source "$DEPS_DIR/miniconda/bin/thisroot.sh" # export CXX="$DEPS_DIR/miniconda/bin/g++" popd diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh index eb79ed00251..112d06aa2ec 100644 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -9,7 +9,7 @@ # conda create --quiet --yes -n my_root_env root_base doxygen -c conda-forge/label/gcc8 # from https://stackoverflow.com/questions/55342122/conda-activate-on-travis-ci -source $(conda info --root)/etc/profile.d/conda.sh +. $(conda info --root)/etc/profile.d/conda.sh conda activate my_root_env echo -en 'travis_fold:start:script.build\\r' diff --git a/.travis.yml b/.travis.yml index 13daca97f93..24cbaaca55e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,8 +48,8 @@ env: before_install: - eval "${MATRIX_EVAL}" - - chmod +x .ci/build_root_${TRAVIS_OS_NAME}.sh - - source .ci/build_root_${TRAVIS_OS_NAME}.sh + - chmod +x .ci/build_root.sh + - source .ci/build_root.sh ${TRAVIS_OS_NAME} # Build your code e.g. by calling make script: From 9b38caac5f09aa577ed4e33df5ad8debcead9a6a Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 20 Apr 2020 10:58:58 +0200 Subject: [PATCH 181/250] fix control predicate for CompiledExpression batch --- AmpGen/CompiledExpression.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index 1bd41d4d1f7..f4bd9e607a7 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -132,7 +132,7 @@ namespace AmpGen stream << typeof() << " * rt, "; stream << CompiledExpressionBase::fcnSignature(typelist(), use_rto(), false) << ") {\n"; stream << "#pragma omp parallel for\n"; - stream << "for( size_t i = 0; i != N/" << utils::size::value << "; ++i ){\n"; + stream << "for( size_t i = 0; i < N/" << utils::size::value << "; ++i ){\n"; if( use_rto() ) stream << progName() + "( r + cacheSize * i, s, x0, x1 + i * eventSize);"; else stream << " rt[cacheSize*i] = " << progName() + "( x0, x1 + i * eventSize);"; stream << "}\n}"; From b18d0484296ff11648c867f16a90bb20c905c6fd Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 20 Apr 2020 11:45:57 +0200 Subject: [PATCH 182/250] remove debug_norm for src/PolarisedSum --- src/PolarisedSum.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index bc0e5df0654..26adb8cd13a 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -202,7 +202,7 @@ void PolarisedSum::prepare() for_each_sequence(m_matrixElements.begin(), m_matrixElements.end(), flagUpdate, updateData, updateInteg); if( m_integrator.isReady() ) updateNorms(); std::for_each( m_matrixElements.begin(), m_matrixElements.end(), resetFlags ); - if( m_nCalls % 10000 == 0 ) debug_norm(); +// if( m_nCalls % 10000 == 0 ) debug_norm(); DEBUG( "m_pdfCache[0] = " << m_pdfCache[0] << " w/o caching = " << (m_weight/m_norm) * getValNoCache(m_events->at(0))); m_pdfCache.update(m_cache, m_probExpression); m_nCalls++; From 5c10f20bd6fcc64323b97fb468d387683551d341 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 20 Apr 2020 11:48:09 +0200 Subject: [PATCH 183/250] try to fix osx ci --- .ci/build_root.sh | 13 +++++++------ .ci/travis_linux.sh | 30 +++++++----------------------- .ci/travis_osx.sh | 9 ++++++--- 3 files changed, 20 insertions(+), 32 deletions(-) mode change 100644 => 100755 .ci/travis_linux.sh diff --git a/.ci/build_root.sh b/.ci/build_root.sh index 6c184476362..e7c51c6d7b6 100755 --- a/.ci/build_root.sh +++ b/.ci/build_root.sh @@ -1,19 +1,20 @@ pushd $DEPS_DIR -if [[ $1 == "osx" ]] ; then - wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh -O miniconda.sh -elif [[ $1 == "linux" ]] ; then - wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh +os=$1 +if [[ $os == "osx" ]] ; then + wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-MacOSX-x86_64.sh -O miniconda_${os}.sh +elif [[ $os == "linux" ]] ; then + wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda_${os}.sh fi -bash miniconda.sh -b -p $DEPS_DIR/miniconda +bash miniconda_${os}.sh -b -p $DEPS_DIR/miniconda_${os} export PATH="$DEPS_DIR/miniconda/bin:$PATH" hash -r conda config --add channels conda-forge conda config --set channel_priority strict # conda install --quiet --yes -c conda-forge/label/gcc8 root_base doxygen -conda create --quiet --yes -n my_root_env root doxygen zstd=1.3.7 -c conda-forge +conda create --quiet --yes -n env_${os} root doxygen zstd=1.3.7 -c conda-forge # conda init bash # source "$DEPS_DIR/miniconda/bin/thisroot.sh" # export CXX="$DEPS_DIR/miniconda/bin/g++" diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh old mode 100644 new mode 100755 index 112d06aa2ec..a216a17c410 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -1,26 +1,18 @@ - -# wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh -# bash miniconda.sh -b -p $DEPS_DIR/miniconda -# export PATH="$DEPS_DIR/miniconda/bin:$PATH" -# hash -r -# conda config --add channels conda-forge -# conda config --set channel_priority strict -# # conda install --quiet --yes -c conda-forge/label/gcc8 root_base doxygen -# conda create --quiet --yes -n my_root_env root_base doxygen -c conda-forge/label/gcc8 +#!/bin/bash # from https://stackoverflow.com/questions/55342122/conda-activate-on-travis-ci +export HOME=/home/tim/ +export PATH="$HOME/miniconda/bin:$PATH" . $(conda info --root)/etc/profile.d/conda.sh -conda activate my_root_env +conda activate env_${TRAVIS_OS_NAME} echo -en 'travis_fold:start:script.build\\r' echo "Building..." echo "Building under OS: $TRAVIS_OS_NAME, CXX =$CXX" set -evx -# -DCMAKE_CXX_COMPILER=$CXX - -mkdir -p build -cd build +mkdir -p build.conda +cd build.conda cmake .. cmake --build . -- -j2 @@ -28,13 +20,5 @@ set +evx cd .. -./build/bin/Generator options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 1000 - - -# echo -e 'travis_fold:end:script.build\\r' -# echo -en 'travis_fold:start:script.test\\r' -# echo "Testing..." -# set -evx - -# ctest --output-on-failure +./build.conda/bin/Generator options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 10000 diff --git a/.ci/travis_osx.sh b/.ci/travis_osx.sh index 18d123b85ee..c974bbc0779 100644 --- a/.ci/travis_osx.sh +++ b/.ci/travis_osx.sh @@ -1,3 +1,8 @@ +#!/bin/bash + +. $(conda info --root)/etc/profile.d/conda.sh +conda activate env_${TRAVIS_OS_NAME} + echo -en 'travis_fold:start:script.build\\r' echo "Building..." echo "Building under OS: $TRAVIS_OS_NAME" @@ -10,9 +15,7 @@ echo "Building ..." cmake --build . -- -j2 cd .. echo "Running test job ..." -./build/bin/Generator options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 1000 - - +./build/bin/Generator options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 10000 # echo -e 'travis_fold:end:script.build\\r' # echo -en 'travis_fold:start:script.test\\r' # echo "Testing..." From df719858562e2e487b793b19e8e4153d2d8f7a95 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 20 Apr 2020 11:54:33 +0200 Subject: [PATCH 184/250] fix travis ci --- .ci/travis_linux.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh index a216a17c410..034ff5af640 100755 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -1,8 +1,6 @@ #!/bin/bash # from https://stackoverflow.com/questions/55342122/conda-activate-on-travis-ci -export HOME=/home/tim/ -export PATH="$HOME/miniconda/bin:$PATH" . $(conda info --root)/etc/profile.d/conda.sh conda activate env_${TRAVIS_OS_NAME} From 5e3fe48a714592aa77f51d5d34285077f740861f Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 20 Apr 2020 11:58:24 +0200 Subject: [PATCH 185/250] fix travis ci --- .ci/travis_linux.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh index 034ff5af640..7cec5a28507 100755 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -1,6 +1,7 @@ #!/bin/bash # from https://stackoverflow.com/questions/55342122/conda-activate-on-travis-ci +export PATH="$DEPS_DIR/miniconda/bin:$PATH" . $(conda info --root)/etc/profile.d/conda.sh conda activate env_${TRAVIS_OS_NAME} From c5d39065cc781894d025b227b8ba476885a6d4b9 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 20 Apr 2020 12:12:41 +0200 Subject: [PATCH 186/250] fix travis ci --- .ci/build_root.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/build_root.sh b/.ci/build_root.sh index e7c51c6d7b6..b0d5e2a436c 100755 --- a/.ci/build_root.sh +++ b/.ci/build_root.sh @@ -7,7 +7,7 @@ elif [[ $os == "linux" ]] ; then wget -nv http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda_${os}.sh fi -bash miniconda_${os}.sh -b -p $DEPS_DIR/miniconda_${os} +bash miniconda_${os}.sh -b -p $DEPS_DIR/miniconda export PATH="$DEPS_DIR/miniconda/bin:$PATH" hash -r conda config --add channels conda-forge From 3f193e8eb90ca1b47922696750eeff740d0db8ee Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 21 Apr 2020 13:51:42 +0200 Subject: [PATCH 187/250] increase verbosity of ci --- .ci/build_root.sh | 7 +++---- .ci/travis_linux.sh | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.ci/build_root.sh b/.ci/build_root.sh index b0d5e2a436c..2364e668a48 100755 --- a/.ci/build_root.sh +++ b/.ci/build_root.sh @@ -1,4 +1,5 @@ pushd $DEPS_DIR +set -evx os=$1 if [[ $os == "osx" ]] ; then @@ -13,9 +14,7 @@ hash -r conda config --add channels conda-forge conda config --set channel_priority strict -# conda install --quiet --yes -c conda-forge/label/gcc8 root_base doxygen conda create --quiet --yes -n env_${os} root doxygen zstd=1.3.7 -c conda-forge -# conda init bash -# source "$DEPS_DIR/miniconda/bin/thisroot.sh" -# export CXX="$DEPS_DIR/miniconda/bin/g++" + +set +evx popd diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh index 7cec5a28507..16acae4bab8 100755 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -1,5 +1,6 @@ #!/bin/bash +set -evx # from https://stackoverflow.com/questions/55342122/conda-activate-on-travis-ci export PATH="$DEPS_DIR/miniconda/bin:$PATH" . $(conda info --root)/etc/profile.d/conda.sh @@ -8,7 +9,6 @@ conda activate env_${TRAVIS_OS_NAME} echo -en 'travis_fold:start:script.build\\r' echo "Building..." echo "Building under OS: $TRAVIS_OS_NAME, CXX =$CXX" -set -evx mkdir -p build.conda cd build.conda From 14e6db13664aa1dc0242e6243b2546b236ab94cc Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 21 Apr 2020 14:10:36 +0200 Subject: [PATCH 188/250] remove --quiet from conda options --- .ci/build_root.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/build_root.sh b/.ci/build_root.sh index 2364e668a48..f49655f951f 100755 --- a/.ci/build_root.sh +++ b/.ci/build_root.sh @@ -14,7 +14,7 @@ hash -r conda config --add channels conda-forge conda config --set channel_priority strict -conda create --quiet --yes -n env_${os} root doxygen zstd=1.3.7 -c conda-forge +conda create --yes -n env_${os} root doxygen zstd=1.3.7 -c conda-forge set +evx popd From 804603f94afc5bf3eaf1a07d8f0639f60671376a Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 22 Apr 2020 09:33:08 +0200 Subject: [PATCH 189/250] chris's fix to build_root --- .ci/build_root.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/build_root.sh b/.ci/build_root.sh index f49655f951f..52c15b244d0 100755 --- a/.ci/build_root.sh +++ b/.ci/build_root.sh @@ -12,9 +12,9 @@ bash miniconda_${os}.sh -b -p $DEPS_DIR/miniconda export PATH="$DEPS_DIR/miniconda/bin:$PATH" hash -r conda config --add channels conda-forge -conda config --set channel_priority strict +# conda config --set channel_priority strict -conda create --yes -n env_${os} root doxygen zstd=1.3.7 -c conda-forge +conda create --yes -n env_${os} root doxygen -c conda-forge set +evx popd From a5a2e683e47d4f552903e06f9028094bccc39dcb Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 22 Apr 2020 09:55:47 +0200 Subject: [PATCH 190/250] A few random fixes for clang --- AmpGen/CoherentSum.h | 8 ++++---- AmpGen/CompiledExpression.h | 2 +- AmpGen/Store.h | 4 +++- AmpGen/simd/avx2d_types.h | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index 0dbd08da458..1a4cfeac4df 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -56,10 +56,10 @@ namespace AmpGen std::string prefix() const { return m_prefix; } auto operator[]( const size_t& index ) { return m_matrixElements[index]; } - const auto operator[]( const size_t& index ) const { return m_matrixElements[index]; } - size_t size() const { return m_matrixElements.size(); } - real_t getWeight() const { return m_weight; } - real_t norm( const Bilinears& norms ) const; + auto operator[]( const size_t& index ) const { return m_matrixElements[index]; } + size_t size() const { return m_matrixElements.size(); } + real_t getWeight() const { return m_weight; } + real_t norm( const Bilinears& norms ) const; real_t norm() const; real_t getNorm( const Bilinears& normalisations ); diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index f4bd9e607a7..9e34ec2c07c 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -121,7 +121,7 @@ namespace AmpGen stream << " if(n == " << i << ") return " << m_externals.at( i ) << ";\n"; stream << " return 0;\n}\n"; } - void compileBatch( std::ostream& stream ) const + void compileBatch( std::ostream& stream ) const override { stream << "#include \n"; stream << "extern \"C\" void " << progName() diff --git a/AmpGen/Store.h b/AmpGen/Store.h index d039e2e9f23..85dc1ed4db5 100644 --- a/AmpGen/Store.h +++ b/AmpGen/Store.h @@ -113,7 +113,9 @@ namespace AmpGen { { auto f = m_index.find( fcn.name() ); if( f == m_index.end() ) FATAL("Expression: " << fcn.name() << " is not registed"); - auto [p0, s] = f->second; + //auto& [p0, s] = f->second; /// bug in the C++ standard. Such fun. + auto p0 = f->second.first; + auto s = f->second.second; if constexpr( std::is_same< typename functor_type::return_type, void >::value ) { diff --git a/AmpGen/simd/avx2d_types.h b/AmpGen/simd/avx2d_types.h index 46565686a49..5ed64e3101e 100644 --- a/AmpGen/simd/avx2d_types.h +++ b/AmpGen/simd/avx2d_types.h @@ -69,7 +69,7 @@ namespace AmpGen { inline __m256i double_to_int( const float_t& x ) { // based on: https://stackoverflow.com/questions/41144668/how-to-efficiently-perform-double-int64-conversions-with-sse-avx - return _mm256_sub_epi64(_mm256_castpd_si256(x + _mm256_set1_pd(0x0018000000000000)), + return _mm256_sub_epi64(_mm256_castpd_si256(_mm256_add_pd(x, _mm256_set1_pd(0x0018000000000000))), _mm256_castpd_si256(_mm256_set1_pd(0x0018000000000000))); } inline float_t gather( const double* base_addr, const float_t& offsets) @@ -121,7 +121,7 @@ namespace AmpGen { stl_fallback( tan ) stl_fallback( sin ) stl_fallback( cos ) - inline float_t remainder( const float_t& a, const float_t& b ){ return a - _mm256_round_pd(a/b, _MM_FROUND_TO_NEG_INF) * b; } + inline float_t remainder( const float_t& a, const float_t& b ){ return a - float_t(_mm256_round_pd(a/b, _MM_FROUND_TO_NEG_INF)) * b; } inline float_t fmod( const float_t& a, const float_t& b ) { auto r = remainder( abs(a), abs(b) ); From 14937c475d473e3fd338c40165617b2f3c75f664 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 22 Apr 2020 10:42:49 +0200 Subject: [PATCH 191/250] fixes for osx --- AmpGen/Store.h | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/AmpGen/Store.h b/AmpGen/Store.h index 85dc1ed4db5..da17cc18911 100644 --- a/AmpGen/Store.h +++ b/AmpGen/Store.h @@ -3,6 +3,9 @@ #include "AmpGen/simd/utils.h" #include "AmpGen/EventList.h" +#ifdef _OPENMP +#include +#endif namespace AmpGen { @@ -44,26 +47,26 @@ namespace AmpGen { m_store.resize(m_nBlocks * m_nFields); } - __always_inline stored_type operator[]( const size_t& index ) const { return m_store[index]; } - __always_inline stored_type& operator[]( const size_t& index ) { return m_store[index]; } + inline stored_type operator[]( const size_t& index ) const { return m_store[index]; } + inline stored_type& operator[]( const size_t& index ) { return m_store[index]; } template unsigned find( const T& t ) const { return m_index.find( t.name() )->second.first; } - __always_inline size_t size() const { return m_nEntries; } - __always_inline size_t nBlocks() const { return m_nBlocks; } - __always_inline size_t nFields() const { return m_nFields; } - __always_inline size_t aligned_size() const { return m_nBlocks * utils::size::value ; } - __always_inline const stored_type& operator()(const size_t& index, const size_t& field) const + inline size_t size() const { return m_nEntries; } + inline size_t nBlocks() const { return m_nBlocks; } + inline size_t nFields() const { return m_nFields; } + inline size_t aligned_size() const { return m_nBlocks * utils::size::value ; } + inline const stored_type& operator()(const size_t& index, const size_t& field) const { if constexpr( align == Alignment::SoA ) return m_store[ field * m_nBlocks + index] ; else return m_store[index*m_nFields+field]; } template - __always_inline const return_type get(const size_t& index, const size_t& field ) const + inline const return_type get(const size_t& index, const size_t& field ) const { return utils::at( operator()( index / utils::size::value, field ), index % utils::size::value ); } - __always_inline const stored_type* data() const { return m_store.data(); } - __always_inline stored_type& operator()(const size_t& index, const size_t& field) + inline const stored_type* data() const { return m_store.data(); } + inline stored_type& operator()(const size_t& index, const size_t& field) { if constexpr( align == Alignment::SoA ) return m_store[ field * m_nBlocks + index] ; else return m_store[index*m_nFields+field]; @@ -133,7 +136,8 @@ namespace AmpGen { #ifdef _OPENMP #pragma omp parallel for #endif - for ( size_t evt = 0; evt < events.size(); ++evt ){ + for ( size_t evt = 0; evt < events.size(); ++evt ) + { auto tmp = fcn( events[evt].address() ); store( evt, p0, &tmp, s); } From d34fd5499e99f43babfcc6b2e2d5b88223ec610f Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 22 Apr 2020 11:01:35 +0200 Subject: [PATCH 192/250] add -fma flag --- Standalone.cmake | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Standalone.cmake b/Standalone.cmake index ec5f4dbc520..600bb8314b7 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -155,14 +155,17 @@ target_compile_options(AmpGen if( ENABLE_AVX2 ) if( "${PRECISION}" MATCHES "DOUBLE" ) - message(STATUS "Enabling AVX2 [double precision]") - target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX2=1" "DOUBLE_PRECISION=1") + message(STATUS "Enabling AVX2 [double precision]") + target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX2=1" "DOUBLE_PRECISION=1") elseif( "${PRECISION}" MATCHES "SINGLE" ) - message(STATUS "Enabling AVX2 [single precision]") - target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX2=1" "DOUBLE_PRECISION=0") - + message(STATUS "Enabling AVX2 [single precision]") + target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX2=1" "DOUBLE_PRECISION=0") endif() target_compile_options(AmpGen PUBLIC -march=native -ftree-vectorize -mavx2 -DHAVE_AVX2_INSTRUCTIONS) + if("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" OR + "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) + target_compile_options(AmpGen PUBLIC -mfma) + endif() endif() if("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" ) From 324b89616c3ec4f77f231a9b56d8883b8226bd10 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 22 Apr 2020 13:09:25 +0200 Subject: [PATCH 193/250] remove std::fabs from unary expression --- src/UnaryExpression.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/UnaryExpression.cpp b/src/UnaryExpression.cpp index 17fb1ae8882..94b0d0db346 100644 --- a/src/UnaryExpression.cpp +++ b/src/UnaryExpression.cpp @@ -28,7 +28,7 @@ DEFINE_UNARY_OPERATOR_NO_RESOLVER( Real, std::real ) DEFINE_UNARY_OPERATOR_NO_RESOLVER( Imag, std::imag ) DEFINE_UNARY_OPERATOR_NO_RESOLVER( ISqrt, rsqrt ) DEFINE_UNARY_OPERATOR_NO_RESOLVER( Conj, std::conj ) -DEFINE_UNARY_OPERATOR_NO_RESOLVER( Abs , std::fabs ) +DEFINE_UNARY_OPERATOR_NO_RESOLVER( Abs , std::abs ) LGamma::LGamma( const Expression& expression) : IUnaryExpression(expression) {} LGamma::operator Expression() const { return Expression( std::make_shared(*this) ) ; } @@ -47,7 +47,7 @@ std::string Abs::to_string( const ASTResolver* resolver ) const { return resolver != nullptr && resolver->enableAVX() ? "abs(" + m_expression.to_string(resolver) +")" : - "std::fabs("+m_expression.to_string(resolver) +")"; + "std::abs("+m_expression.to_string(resolver) +")"; } std::string Conj::to_string( const ASTResolver* resolver ) const From 94ae6402ef519f47f20ee85a164faf093e83a428 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 22 Apr 2020 13:52:04 +0200 Subject: [PATCH 194/250] still applying fixes for osx --- AmpGen/CompilerWrapper.h | 2 ++ AmpGen/Particle.h | 2 +- src/CompilerWrapper.cpp | 10 +++++++++- src/Particle.cpp | 3 ++- src/PolarisedSum.cpp | 12 +++++------- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/AmpGen/CompilerWrapper.h b/AmpGen/CompilerWrapper.h index 1e17d9eb03c..a7f20be2439 100644 --- a/AmpGen/CompilerWrapper.h +++ b/AmpGen/CompilerWrapper.h @@ -22,11 +22,13 @@ namespace AmpGen void setVerbose() { m_verbose = true ; } void preamble(std::ostream& os ) const ; void addHeader(const std::string& include ) { m_includes.push_back(include); } + private: std::vector m_includes = {"array","complex","math.h","vector"}; bool m_verbose; std::string m_cxx; std::string generateFilename(); + bool isClang() const; }; } // namespace AmpGen #endif diff --git a/AmpGen/Particle.h b/AmpGen/Particle.h index 9dd3609d1b6..593fc2663b5 100644 --- a/AmpGen/Particle.h +++ b/AmpGen/Particle.h @@ -258,7 +258,7 @@ namespace AmpGen Expression propagator( DebugSymbols* db = nullptr ) const; /// Calculates the total expression for this particle, including symmetrisation and the current polarisation state - Expression getExpression( DebugSymbols* db = nullptr, const unsigned int& index = 0 ); + Expression getExpression( DebugSymbols* db = nullptr, const std::vector& = {} ); /// Calculate the transition matrix for this decay Tensor transitionMatrix( DebugSymbols* db = nullptr ); diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index b018506382e..b27e031bb34 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -124,6 +124,11 @@ bool CompilerWrapper::compile( std::vector& expressions return true; } +bool CompilerWrapper::isClang() const +{ + return m_cxx.find("clang") != std::string::npos || m_cxx.find("llvm-g++") != std::string::npos; +} + std::string get_cpp_version(){ if( __cplusplus >= 201703L ) return "c++17"; if( __cplusplus >= 201402L ) return "c++14"; @@ -151,12 +156,15 @@ void CompilerWrapper::compileSource( const std::string& fname, const std::string "-rdynamic", "-fPIC"}; std::transform( compile_flags.begin(), compile_flags.end(), std::back_inserter(argp), [](const auto& flag ){return flag.c_str() ; } ); - if( m_cxx.find("clang") != std::string::npos || m_cxx.find("llvm-g++") != std::string::npos) + if(isClang()) { argp.push_back( "-Wno-return-type-c-linkage"); #if __APPLE__ argp.push_back("-lstdc++"); #endif + #ifdef _OPENMP + argp.push_back("-fopenmp=libiomp5"); + #endif } argp.push_back( fname.c_str() ); diff --git a/src/Particle.cpp b/src/Particle.cpp index fdd239cc255..caa73e54681 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -372,8 +372,9 @@ Tensor Particle::transitionMatrix( DebugSymbols* db ) return spinTensor(); } -Expression Particle::getExpression( DebugSymbols* db, const unsigned int& index ) +Expression Particle::getExpression( DebugSymbols* db, const std::vector& state) { + if( state.size() !=0 ) setPolarisationState( state ); if( db != nullptr && !isStable() ) db->emplace_back( uniqueString() , Parameter( "NULL", 0, true ) ); Expression total = 0; diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 26adb8cd13a..86e748a55e0 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "AmpGen/CompilerWrapper.h" #include "AmpGen/NamedParameter.h" @@ -68,17 +69,14 @@ PolarisedSum::PolarisedSum(const EventType& type, auto protoAmps = m_rules.getMatchingRules(m_eventType); for(const auto& m : protoAmps ) INFO( m.first.uniqueString() ); m_matrixElements.resize( protoAmps.size() ); - ThreadPool tp(8); + ThreadPool tp( std::thread::hardware_concurrency() ); for(unsigned i = 0; i < m_matrixElements.size(); ++i) { - tp.enqueue( [i, &protoAmps, &polStates, this]{ + // tp.enqueue( [i, &protoAmps, &polStates, this]{ Tensor thisExpression( Tensor::dim(polStates.size()) ); auto& [p, coupling] = protoAmps[i]; DebugSymbols syms; - for(unsigned j = 0; j != polStates.size(); ++j){ - p.setPolarisationState( polStates[j] ); - thisExpression[j] = make_cse( p.getExpression(&syms) ); - } + for(unsigned j = 0; j != polStates.size(); ++j) thisExpression[j] = make_cse( p.getExpression(&syms, polStates[j] ) ); m_matrixElements[i] = TransitionMatrix( p, coupling, @@ -87,7 +85,7 @@ PolarisedSum::PolarisedSum(const EventType& type, p.decayDescriptor(), this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,this->m_mps ) ); CompilerWrapper().compile( m_matrixElements[i] ); - }); + // }); } } if ( stype == spaceType::flavour ) From 2f14291cdc803d7e8c10471c57391c208006370c Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 28 Apr 2020 13:21:00 +0200 Subject: [PATCH 195/250] cleanup of AVX code, add AVX512, fixes to spline shapes --- .ci/travis_osx.sh | 2 +- AmpGen/AmplitudeRules.h | 10 +- AmpGen/Array.h | 4 +- AmpGen/Chi2Estimator.h | 4 +- AmpGen/CoherentSum.h | 4 +- AmpGen/CompiledExpression.h | 47 +++--- AmpGen/Event.h | 1 + AmpGen/EventList.h | 12 +- AmpGen/EventType.h | 1 + AmpGen/Generator.h | 64 +++++---- AmpGen/Integrator.h | 2 +- AmpGen/PolarisedSum.h | 4 +- AmpGen/Spline.h | 6 +- AmpGen/SumPDF.h | 7 +- AmpGen/TreeReader.h | 192 ++++++++++++------------- AmpGen/Units.h | 13 ++ AmpGen/simd/avx2_types.h | 127 ----------------- AmpGen/simd/avx2d_types.h | 206 ++++++++++++++------------- AmpGen/simd/avx2f_types.h | 128 +++++++++++++++++ AmpGen/simd/avx512d_types.h | 212 ++++++++++++++++++++++++++++ AmpGen/simd/utils.h | 68 ++++----- Standalone.cmake | 33 +++-- apps/DataConverter.cpp | 31 ++-- doc/release.notes | 5 + examples/FitterWithPolarisation.cpp | 2 +- examples/SignalOnlyFitter.cpp | 2 +- src/Array.cpp | 17 +-- src/CoherentSum.cpp | 19 +-- src/CompiledExpressionBase.cpp | 7 +- src/CompilerWrapper.cpp | 12 +- src/Event.cpp | 10 +- src/EventList.cpp | 78 +++++----- src/EventListSIMD.cpp | 4 +- src/EventType.cpp | 39 ++++- src/Expression.cpp | 20 +-- src/Integrator.cpp | 2 +- src/PolarisedSum.cpp | 4 +- src/Projection.cpp | 2 +- src/Spline.cpp | 23 +-- src/TreeReader.cpp | 34 +++++ src/Units.cpp | 13 ++ src/Utilities.cpp | 13 +- test/test_avx2d.cpp | 34 ++--- 43 files changed, 916 insertions(+), 602 deletions(-) delete mode 100644 AmpGen/simd/avx2_types.h create mode 100644 AmpGen/simd/avx2f_types.h create mode 100644 AmpGen/simd/avx512d_types.h create mode 100644 src/TreeReader.cpp create mode 100644 src/Units.cpp diff --git a/.ci/travis_osx.sh b/.ci/travis_osx.sh index c974bbc0779..2ca3917298e 100644 --- a/.ci/travis_osx.sh +++ b/.ci/travis_osx.sh @@ -10,7 +10,7 @@ echo "Building under OS: $TRAVIS_OS_NAME" mkdir -p build cd build echo "CMake-ing, CXX = $CXX" -cmake .. -DCMAKE_CXX_COMPILER=clang +cmake .. -DCMAKE_CXX_COMPILER=clang -DUSE_SIMD="" echo "Building ..." cmake --build . -- -j2 cd .. diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index 27a3be5991c..f7d0be128a2 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -14,7 +14,7 @@ #include "AmpGen/Event.h" #include "AmpGen/Particle.h" #include "AmpGen/ExpressionParser.h" -#if ENABLE_AVX2 +#if ENABLE_AVX #include "AmpGen/EventListSIMD.h" #endif @@ -105,14 +105,18 @@ namespace AmpGen decayTree(dt), coupling(coupling) {} - #if ENABLE_AVX2 + #if ENABLE_AVX const RT operator()(const Event& event) const { return amp_type::operator()(EventListSIMD::makeEvent(event).data()); } + void debug( const Event& event ) const { amp_type::debug(EventListSIMD::makeEvent(event).data() ) ; } + #else const RT operator()(const Event& event) const { return amp_type::operator()(event.address()) ; } + void debug( const Event& event ) const { amp_type::debug(event.address()) ; } #endif template auto operator()(arg_types... args ) const { return amp_type::operator()(args...) ; } const RT operator()(const float_v* t) const { return amp_type::operator()(t) ; } + void debug( const float_v* t ) const { amp_type::debug(t) ; } const std::string decayDescriptor() const { return decayTree.decayDescriptor() ; } Particle decayTree; @@ -174,7 +178,7 @@ namespace AmpGen const std::vector operator()(const Event& event) const { std::vector rt(4); - #if ENABLE_AVX2 + #if ENABLE_AVX amp_type::operator()(rt.data(), 1, externBuffer().data(), EventListSIMD::makeEvent(event).data()); #else amp_type::operator()(rt.data(), 1, externBuffer().data(), event.address()); diff --git a/AmpGen/Array.h b/AmpGen/Array.h index f53d5ea39ab..312cd465e08 100644 --- a/AmpGen/Array.h +++ b/AmpGen/Array.h @@ -31,11 +31,11 @@ namespace AmpGen complex_t operator()() const override; Expression operator[]( const Expression& address ) const; Expression top() const { return m_top ; } - + unsigned size() const { return m_size; } private: Expression m_top; Expression m_address; - size_t m_size; + unsigned m_size; }; } // namespace AmpGen diff --git a/AmpGen/Chi2Estimator.h b/AmpGen/Chi2Estimator.h index 841cfa76cc7..ea92e4d09de 100644 --- a/AmpGen/Chi2Estimator.h +++ b/AmpGen/Chi2Estimator.h @@ -7,7 +7,7 @@ #include "AmpGen/BinDT.h" -#if ENABLE_AVX2 +#if ENABLE_AVX #include "AmpGen/EventListSIMD.h" #else #include "AmpGen/EventList.h" @@ -21,7 +21,7 @@ namespace AmpGen class Chi2Estimator { - #if ENABLE_AVX2 + #if ENABLE_AVX typedef EventListSIMD EventList_type; #else typedef EventList EventList_type; diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index 1a4cfeac4df..c50404fa02e 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -43,7 +43,7 @@ namespace AmpGen class CoherentSum { public: - #if ENABLE_AVX2 + #if ENABLE_AVX using EventList_type = EventListSIMD; #else using EventList_type = EventList; @@ -76,7 +76,7 @@ namespace AmpGen void reset( bool resetEvents = false ); void setEvents( const EventList_type& list ); void setMC( const EventList_type& sim ); - #if ENABLE_AVX2 + #if ENABLE_AVX void setEvents( const EventList& list) { m_ownEvents = true; setEvents( *(new EventListSIMD(list)) ) ; } void setMC( const EventList& list) { setMC( *(new EventListSIMD(list)) ) ; } #endif diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index 9e34ec2c07c..eaf86b1c5d2 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -36,7 +36,7 @@ namespace AmpGen private: DynamicFCN m_fcn; DynamicFCN m_batchFcn; - DynamicFCN>(ARGS...)> m_fdb; + DynamicFCN>(ARGS...)> m_fdb; std::vector m_externals = {}; bool m_hasExternalsChanged = {false}; @@ -100,10 +100,9 @@ namespace AmpGen m_externals[address] = value; m_hasExternalsChanged = true; } - void resizeExternalCache(const size_t& N ) override { - if( m_externals.size() < N ){ - m_externals.resize(N); - } + void resizeExternalCache(const size_t& N ) override + { + if( m_externals.size() < N ) m_externals.resize(N); } bool hasExternalsChanged() { return m_hasExternalsChanged; } void resetExternals() { m_hasExternalsChanged = false; } @@ -165,26 +164,26 @@ namespace AmpGen m_batchFcn(args...); } - template < class T> - void debug( const T* event ) const - { - if ( !m_fcn.isLinked() ) { - FATAL( "Function " << name() << " not linked" ); - } - if ( !m_fdb.isLinked() ) { - FATAL( "Function" << name() << " debugging symbols not linked" ); - } - std::vector> debug_results; - if constexpr(std::is_same::value) debug_results = m_fdb( nullptr, &( m_externals[0] ), event ); - else debug_results = m_fdb( &(m_externals[0]), event); - for( auto& debug_result : debug_results ){ - auto val = debug_result.second; - auto label = debug_result.first; - if( std::real(val) == -999. ) std::cout << bold_on << std::setw(50) << std::left << label << bold_off << std::endl; - else if( std::imag(val) == 0 ) std::cout << " " << std::setw(50) << std::left << label << " = " << std::real(val) << std::endl; - else std::cout << " " << std::setw(50) << std::left << label << " = " << val << std::endl; - } + template < class T> void debug( const T* event ) const + { + if ( !m_fcn.isLinked() ) { + FATAL( "Function " << name() << " not linked" ); } + if ( !m_fdb.isLinked() ) { + FATAL( "Function" << name() << " debugging symbols not linked" ); + } + std::vector> debug_results; + if constexpr(std::is_same::value) debug_results = m_fdb( nullptr, &( m_externals[0] ), event ); + else debug_results = m_fdb( &(m_externals[0]), event); + for( auto& debug_result : debug_results ){ + auto val = debug_result.second; + auto label = debug_result.first; + if( utils::all_of(val.real(), -999.) ) std::cout << bold_on << std::setw(50) << std::left << label << bold_off << std::endl; + else if( utils::all_of(val.imag(), 0.) ) std::cout << " " << std::setw(50) << std::left << label << " = " << val.real() << std::endl; + else + std::cout << " " << std::setw(50) << std::left << label << " = " << val << std::endl; + } + } bool link( void* handle ) override { diff --git a/AmpGen/Event.h b/AmpGen/Event.h index 01bc5139f16..5e420599f1b 100644 --- a/AmpGen/Event.h +++ b/AmpGen/Event.h @@ -53,6 +53,7 @@ namespace AmpGen { real_t s( const unsigned& index1, const unsigned& index2 ) const ; real_t s( const unsigned& index1, const unsigned& index2, const unsigned& index3 ) const; real_t s( const std::vector& indices ) const ; + void reorder( const std::vector& addresses); private: std::vector m_event; real_t m_genPdf = {1}; diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index d96f5326c91..aadd68eea37 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -8,6 +8,7 @@ #include "AmpGen/Projection.h" #include "AmpGen/Utilities.h" #include "AmpGen/MetaUtils.h" +#include "AmpGen/Units.h" #include #include @@ -71,10 +72,13 @@ namespace AmpGen size_t aligned_size() const { return m_data.size() ; } size_t nBlocks() const { return m_data.size() ; } double integral() const; + const double* block(const unsigned pos) const { return m_data[pos].address(); } real_t weight( const size_t& pos) const { return m_data[pos].weight(); } real_t genPDF( const size_t& pos) const { return m_data[pos].genPdf(); } void reserve( const size_t& size ) { m_data.reserve( size ); } + void resize ( const size_t& size ) { m_data.resize(size) ; } void push_back( const Event& evt ) { m_data.push_back( evt ); } + void emplace_back( const Event& evt) { m_data.emplace_back(evt) ; } void setEventType( const EventType& type ) { m_eventType = type; } void add( const EventList& evts ); void loadFromTree( TTree* tree, const ArgumentPack& args ); @@ -132,15 +136,17 @@ namespace AmpGen { return std::count_if( std::begin(*this), std::end(*this), fcn ); } - }; - DECLARE_ARGUMENT(Branches, std::vector); + }; + DECLARE_ARGUMENT(Branches, std::vector); /// Branch names containing kinematic information + DECLARE_ARGUMENT(ExtraBranches, std::vector); /// additional information about the event to include + DECLARE_ARGUMENT(IdBranches, std::vector); /// Branches containing PID information, used if the names of particles are incorrect (looking at you, DTF) DECLARE_ARGUMENT(EntryList, std::vector); DECLARE_ARGUMENT(GetGenPdf, bool); DECLARE_ARGUMENT(Filter, std::string); DECLARE_ARGUMENT(WeightBranch, std::string); DECLARE_ARGUMENT(ApplySym, bool); DECLARE_ARGUMENT(WeightFunction, std::function); - + DECLARE_ARGUMENT(InputUnits, AmpGen::Units); } // namespace AmpGen #endif diff --git a/AmpGen/EventType.h b/AmpGen/EventType.h index 93fa1467f03..d2777c0143a 100644 --- a/AmpGen/EventType.h +++ b/AmpGen/EventType.h @@ -62,6 +62,7 @@ namespace AmpGen /// Functor to randomly symmetrise data of this event type, using the Fisher-Yates shuffle. std::function symmetriser() const; + std::function& ids)> automaticOrdering() const; /// Calculates the number of spin indices associated with the initial and final state, i.e. the rank of the relevant transition matrix. std::pair dim() const; diff --git a/AmpGen/Generator.h b/AmpGen/Generator.h index 4a97856dadd..670c6838850 100644 --- a/AmpGen/Generator.h +++ b/AmpGen/Generator.h @@ -33,37 +33,40 @@ namespace AmpGen m_rnd = rand; m_gps.setRandom( m_rnd ); } - void fillEventListPhaseSpace( EventList& list, const size_t& N) - { - list.reserve( N ); - while( list.size() < N ){ - Event newEvent = m_gps.makeEvent(); - newEvent.setWeight( 1 ); - newEvent.setIndex( list.size() ); - list.push_back( newEvent ); - } - } void setBlockSize( const size_t& blockSize ) { m_generatorBlock = blockSize; } void setNormFlag( const bool& normSetting ) { m_normalise = normSetting; } - template void fillEventListPhaseSpace( EventList& list, const size_t& N, HARD_CUT cut) + template void fillEventListPhaseSpace( EventList& list, const size_t& N, cut_type cut = nullptr) { - list.reserve( N ); - while( list.size() < N ){ - Event newEvent = m_gps.makeEvent(); - newEvent.setWeight( 1 ); - if ( cut( newEvent ) ){ - newEvent.setIndex( list.size() ); - list.push_back( newEvent ); + if constexpr( std::is_same::value ) + { + if( cut != nullptr ) FATAL("This shouldn't happen..."); + list.resize(N); +// #pragma omp parallel for + for( unsigned int i = 0 ; i != N; ++i ) + { + list[i] = m_gps.makeEvent(); + list[i].setWeight( 1 ); + list[i].setIndex(i); + } + } + else { + list.reserve( N ); + while( list.size() < N ){ + Event newEvent = m_gps.makeEvent(); + newEvent.setWeight( 1 ); + if ( cut( newEvent ) ){ + newEvent.setIndex( list.size() ); + list.push_back( newEvent ); + } } } } - template - void fillEventList( PDF& pdf, EventList& list, const size_t& N ) - { - fillEventList( pdf, list, N, []( const Event& /*evt*/ ) { return 1; } ); - } + template void fillEventList( PDF& pdf, EventList& list, const size_t& N ) + { + fillEventList( pdf, list, N, nullptr); + } template void fillEventList( PDF& pdf, EventList& list, const size_t& N, HARD_CUT cut ) @@ -77,7 +80,7 @@ namespace AmpGen auto tStartTotal = std::chrono::high_resolution_clock::now(); pdf.reset( true ); ProgressBar pb(60, detail::trimmedString(__PRETTY_FUNCTION__) ); - ProfileClock t_phsp, t_eval, t_acceptReject; + ProfileClock t_phsp, t_eval, t_acceptReject, t_gather; std::vector efficiencyReport(m_generatorBlock,false); while ( list.size() - size0 < N ) { @@ -85,8 +88,10 @@ namespace AmpGen t_phsp.start(); fillEventListPhaseSpace(mc, m_generatorBlock, cut); t_phsp.stop(); - t_eval.start(); + t_gather.start(); pdf.setEvents( mc ); + t_gather.stop(); + t_eval.start(); pdf.prepare(); t_eval.stop(); if ( maxProb == 0 ) { @@ -133,10 +138,11 @@ namespace AmpGen } pb.finish(); double time = std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); - INFO( "Generated " << N << " events in " << time << " ms" ); - INFO( "Generating phase space : " << t_phsp << " ms"); - INFO( "Evaluating PDF : " << t_eval << " ms"); - INFO( "Doing accept/reject : " << t_acceptReject << " ms"); + INFO("Generated " << N << " events in " << time << " ms"); + INFO("Generating phase space : " << t_phsp << " ms"); + INFO("Evaluating PDF : " << t_eval << " ms"); + INFO("Doing accept/reject : " << t_acceptReject << " ms"); + INFO("Gathering : " << t_gather << " ms"); } template ::value>::type> EventList generate(PDF& pdf, const size_t& nEvents ) diff --git a/AmpGen/Integrator.h b/AmpGen/Integrator.h index f1f4f7c6c40..d7856376028 100644 --- a/AmpGen/Integrator.h +++ b/AmpGen/Integrator.h @@ -53,7 +53,7 @@ namespace AmpGen template void updateCache(const T& expression) { - #if ENABLE_AVX2 + #if ENABLE_AVX if( m_events != nullptr ) m_cache.update( static_cast(m_events)->store(), expression ); #else if( m_events != nullptr ) m_cache.update( static_cast(m_events)->store(), expression ); diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index f9908ab196f..a2d0a555e52 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -36,7 +36,7 @@ namespace AmpGen class PolarisedSum { public: - #if ENABLE_AVX2 + #if ENABLE_AVX using EventList_type = EventListSIMD; #else using EventList_type = EventList; @@ -47,7 +47,7 @@ namespace AmpGen void prepare(); void setEvents(EventList_type&); void setMC(EventList_type&); - #if ENABLE_AVX2 + #if ENABLE_AVX void setEvents(EventList& evts){ m_ownEvents = true; setEvents( *new EventList_type(evts)) ; }; void setMC(EventList& evts){ setMC( *new EventList_type(evts)) ; }; #endif diff --git a/AmpGen/Spline.h b/AmpGen/Spline.h index 4ce5696911b..7ceadd03b6d 100644 --- a/AmpGen/Spline.h +++ b/AmpGen/Spline.h @@ -49,13 +49,13 @@ namespace AmpGen{ const double& min, const double& max ); - Spline( const Spline& spline, const Expression& x ); + Spline( const Spline& spline, const Expression& x, DebugSymbols* db =nullptr ); void resolve( ASTResolver& resolver ) const override ; std::string to_string(const ASTResolver* resolver=nullptr) const override; operator Expression() ; complex_t operator()() const override ; - Expression operator()( const Expression& x ); - Expression eval() const ; + Expression operator()( const Expression& x, DebugSymbols* db); + Expression eval(DebugSymbols* db=nullptr) const ; Array m_points; std::string m_name; diff --git a/AmpGen/SumPDF.h b/AmpGen/SumPDF.h index 340f7aa18f9..dd096cbffca 100644 --- a/AmpGen/SumPDF.h +++ b/AmpGen/SumPDF.h @@ -8,8 +8,7 @@ #include "AmpGen/LiteSpan.h" #include -#if ENABLE_AVX2 - #include "AmpGen/simd/avx2_types.h" +#if ENABLE_AVX #include "AmpGen/simd/utils.h" #endif @@ -69,7 +68,7 @@ namespace AmpGen } return -2 * LL; } - #if ENABLE_AVX2 + #if ENABLE_AVX if constexpr( std::is_same::value ) { float_v LL = 0.f; @@ -77,7 +76,7 @@ namespace AmpGen #pragma omp parallel for reduction( +: LL ) for ( size_t block = 0; block < m_events->nBlocks(); ++block ) { - LL += m_events->weight(block) * AVX2d::log(this->operator()(m_events->block(block), block)); + LL += m_events->weight(block) * AVX::log(this->operator()(m_events->block(block), block)); } return -2 * utils::sum_elements(LL); } diff --git a/AmpGen/TreeReader.h b/AmpGen/TreeReader.h index 64e9924f8cf..d808025d423 100644 --- a/AmpGen/TreeReader.h +++ b/AmpGen/TreeReader.h @@ -5,115 +5,105 @@ #include "TLeaf.h" #include "TTree.h" #include - +#include "AmpGen/MetaUtils.h" namespace AmpGen { - template - class TreeReader - { - private: - struct IReadBranch { - std::string name; - IReadBranch( const std::string& name = "" ) : name( name ) {} - virtual void* address() const = 0; - virtual void transfer() = 0; - virtual ~IReadBranch() = default; - }; - - template struct ReadBranch : public IReadBranch { - InputType thing; - OutputType* output; - void* address() const override { return (void*)&thing; } - ReadBranch( const std::string& name, OutputType* outputBranch ) : IReadBranch( name ), output( outputBranch ) {} - void transfer() override { *output = thing; } - }; - - template struct ReinterpretBranch : public IReadBranch { - InputType thing; - OutputType* output; - void* address() const override { return (void*)&thing; } - ReinterpretBranch( const std::string& name, OutputType* outputBranch ) : IReadBranch( name ), output( outputBranch ) {} - void transfer() override { *output = reinterpret_cast(thing); } - }; - - struct Branch { - OutputType* value; - Branch() : value( new OutputType() ) {} - ~Branch() { delete value; } - operator OutputType() const { return *value; } - operator OutputType&() { return *value; } - OutputType* operator&() { return value; } - }; + class TreeReader + { + private: + struct IReadBranch { + std::string name; + IReadBranch( const std::string& name = "" ) : name( name ) {} + virtual void* address() const = 0; + virtual void transfer() = 0; + virtual ~IReadBranch() = default; + }; - struct Iterator { - size_t m_position; - TreeReader* m_parent; - Iterator( const size_t& pos, TreeReader* parent ) : m_position( pos ), m_parent( parent ) {} - Iterator& operator++() - { - m_position++; - m_parent->getEntry( m_position ); - return *this; - } - bool operator==( const Iterator& rhs ) const { return m_position == rhs.m_position; } - bool operator!=( const Iterator& rhs ) const { return m_position != rhs.m_position; } - size_t operator*() const { return m_position; } - }; - TTree* tree = {nullptr}; - bool ready = {false}; - std::vector branches = {}; + template struct ReadBranch : public IReadBranch + { + InputType thing; + OutputType* output; + void* address() const override { return (void*)&thing; } + ReadBranch( const std::string& name, OutputType* outputBranch ) : IReadBranch( name ), output( outputBranch ) {} + void transfer() override { *output = thing; } + }; - public: - explicit TreeReader( TTree* tree ) : tree( tree ) {} - void setBranch( const std::string& name, OutputType* ptr ) + template struct ReinterpretBranch : public IReadBranch + { + InputType thing; + OutputType* output; + void* address() const override { return (void*)&thing; } + ReinterpretBranch( const std::string& name, OutputType* outputBranch ) : IReadBranch( name ), output( outputBranch ) {} + void transfer() override { *output = reinterpret_cast(thing); } + }; + struct Iterator { + size_t m_position; + TreeReader* m_parent; + Iterator( const size_t& pos, TreeReader* parent ) : m_position( pos ), m_parent( parent ) {} + Iterator& operator++() { - IReadBranch* new_branch = nullptr; - TLeaf* leaf = tree->GetLeaf( name.c_str() ); - if( leaf == nullptr ){ - ERROR( "Leaf: " << name << " not found"); - return; - } - std::string branchType = leaf->GetTypeName(); - if( branchType == "Double_t" ) new_branch = new ReadBranch( name, ptr ); - if( branchType == "Float_t" ) new_branch = new ReadBranch( name, ptr ); - if( branchType == "Bool_t" ) new_branch = new ReadBranch( name, ptr ); - if( branchType == "Int_t" ) new_branch = new ReadBranch( name, ptr ); - if( branchType == "UInt_t" ) new_branch = new ReadBranch( name, ptr ); - if( branchType == "ULong64_t") new_branch = new ReadBranch( name, ptr ); - if( new_branch == nullptr ){ - ERROR( "Branch type:" << branchType << " not recognised" ); - return; - } - ready = false; - branches.push_back( new_branch ); + m_position++; + m_parent->getEntry( m_position ); + return *this; } - Branch bind( const std::string& name ) - { - Branch rt; - setBranch( name, &rt ); - return rt; + bool operator==( const Iterator& rhs ) const { return m_position == rhs.m_position; } + bool operator!=( const Iterator& rhs ) const { return m_position != rhs.m_position; } + size_t operator*() const { return m_position; } + }; + TTree* m_tree = {nullptr}; + bool m_ready = {false}; + std::vector m_branches = {}; + std::vector m_entryList = {}; + public: + template struct Proxy + { + OutputType* data; + Proxy() : data( new OutputType() ) {} + operator OutputType() const { return *data; } + ~Proxy(){ delete data ; } + }; + explicit TreeReader( TTree* tree ); + template Proxy make_proxy( const std::string& name ) + { + Proxy rt; + setBranch( name, rt.data ); + return rt; + } + template void setBranch( const std::string& name, OutputType& thing ) { + setBranch(name,&thing) ; } + template void setBranch( const std::string& name, OutputType* ptr ) + { + IReadBranch* new_branch = nullptr; + TLeaf* leaf = m_tree->GetLeaf( name.c_str() ); + if( leaf == nullptr ){ + ERROR( "Leaf: " << name << " not found"); + return; } - void getEntry( const unsigned int& entry ) - { - if ( !ready ) prepare(); - tree->GetEntry( entry ); - for ( auto& branch : branches ) branch->transfer(); - } - void prepare() - { - for ( auto& branch : branches ) { - tree->SetBranchStatus( branch->name.c_str(), "1" ); - tree->SetBranchAddress( branch->name.c_str(), branch->address() ); - } - ready = true; - } - ~TreeReader() - { - for ( auto& branch : branches ) delete branch; + std::string branchType = leaf->GetTypeName(); + if( branchType == "Double_t" ) new_branch = new ReadBranch( name, ptr ); + if( branchType == "Float_t" ) new_branch = new ReadBranch( name, ptr ); + if( branchType == "Bool_t" ) new_branch = new ReadBranch( name, ptr ); + if( branchType == "Int_t" ) new_branch = new ReadBranch( name, ptr ); + if( branchType == "UInt_t" ) new_branch = new ReadBranch( name, ptr ); + if( branchType == "ULong64_t") new_branch = new ReadBranch( name, ptr ); + if( new_branch == nullptr ){ + ERROR( "Branch type:" << branchType << " not recognised" ); + return; } - Iterator begin() { return Iterator( 0, this ); } - Iterator end() { return Iterator( tree->GetEntries(), this ); } - }; + DEBUG("Making branch with properties: [name = " << name << ", input type = " << branchType << " output type = " << typeof() << "]" ); + m_ready = false; + m_branches.push_back( new_branch ); + } + void setEntryList( const std::vector& entryList ); + void unsetEntryList(); + void getEntry( const unsigned int& entry ); + void prepare(); + size_t nEntries() const; + ~TreeReader(); + Iterator begin(); + Iterator end(); + }; +// ENABLE_DEBUG(TreeReader); } // namespace AmpGen #endif diff --git a/AmpGen/Units.h b/AmpGen/Units.h index fc9db3fddd2..9e376d122d7 100644 --- a/AmpGen/Units.h +++ b/AmpGen/Units.h @@ -1,10 +1,23 @@ #ifndef AMPGEN_UNITS_H #define AMPGEN_UNITS_H 1 +#include "AmpGen/enum.h" namespace AmpGen { +/* + struct NewUnits { + static unsigned TeV = 0; + static unsigned GeV = 1; + static unsigned MeV = 2; + static unsigned KeV = 3; + + }; +*/ static const double TeV = 1000; static const double GeV = 1; static const double MeV = 0.001; static const double KeV = 0.001*0.001; + + declare_enum( Units, TeV, GeV, MeV, KeV ) + double to_double(const Units& unit ); } #endif diff --git a/AmpGen/simd/avx2_types.h b/AmpGen/simd/avx2_types.h deleted file mode 100644 index 04579d4ad73..00000000000 --- a/AmpGen/simd/avx2_types.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef AMPGEN_AVX_TYPES -#define AMPGEN_AVX_TYPES 1 - -#include -#include -#include -#include -#include "AmpGen/simd/avx_mathfun.h" -#include - -namespace AmpGen { - namespace AVX2 { - struct float_t { - __m256 data; - static constexpr unsigned size = 8 ; - typedef float scalar_type; - float_t() = default; - float_t(__m256 data ) : data(data) {} - float_t(const float& f ) : data( _mm256_set1_ps(f) ) {} - float_t(const double& f ) : data( _mm256_set1_ps( float(f) )) {} - float_t(const float* f ) : data( _mm256_loadu_ps( f ) ) {} - void store( float* ptr ) const { _mm256_storeu_ps( ptr, data ); } - std::array to_array() const { std::array b; store( &b[0] ); return b; } - float at(const unsigned i) const { return to_array()[i] ; } - operator __m256() const { return data ; } - }; - - inline float_t operator+( const float_t& lhs, const float_t& rhs ) { return _mm256_add_ps(lhs, rhs); } - inline float_t operator-( const float_t& lhs, const float_t& rhs ) { return _mm256_sub_ps(lhs, rhs); } - inline float_t operator*( const float_t& lhs, const float_t& rhs ) { return _mm256_mul_ps(lhs, rhs); } - inline float_t operator/( const float_t& lhs, const float_t& rhs ) { return _mm256_div_ps(lhs, rhs); } - inline float_t operator-( const float_t& x ) { return -1.f * x; } - inline float_t operator&( const float_t& lhs, const float_t& rhs ) { return _mm256_and_ps( lhs, rhs ); } - inline float_t operator|( const float_t& lhs, const float_t& rhs ) { return _mm256_or_ps( lhs, rhs ); } - inline float_t operator^( const float_t& lhs, const float_t& rhs ) { return _mm256_xor_ps( lhs, rhs ); } - inline float_t operator+=(float_t& lhs, const float_t& rhs ){ lhs = lhs + rhs; return lhs; } - inline float_t operator-=(float_t& lhs, const float_t& rhs ){ lhs = lhs - rhs; return lhs; } - inline float_t operator*=(float_t& lhs, const float_t& rhs ){ lhs = lhs * rhs; return lhs; } - inline float_t operator/=(float_t& lhs, const float_t& rhs ){ lhs = lhs / rhs; return lhs; } - inline float_t operator&&( const float_t& lhs, const float_t& rhs ) { return _mm256_and_ps( lhs, rhs ); } - inline float_t operator||( const float_t& lhs, const float_t& rhs ) { return _mm256_or_ps( lhs, rhs ); } - inline float_t operator!( const float_t& x ) { return x ^ _mm256_castsi256_ps( _mm256_set1_epi32( -1 ) ); } - inline float_t operator<( const float_t& lhs, const float_t& rhs ) { return _mm256_cmp_ps( lhs, rhs, _CMP_LT_OS ); } - inline float_t operator>( const float_t& lhs, const float_t& rhs ) { return _mm256_cmp_ps( lhs, rhs, _CMP_GT_OS ); } - inline float_t operator==( const float_t& lhs, const float_t& rhs ){ return _mm256_cmp_ps( lhs, rhs, _CMP_EQ_OS ); } - inline float_t sqrt( const float_t& v ) { return _mm256_sqrt_ps(v); } - inline float_t sin( const float_t& v ) { return sin256_ps(v) ; } - inline float_t cos( const float_t& v ) { return cos256_ps(v) ; } - inline float_t tan( const float_t& v ) { float_t s; float_t c; sincos256_ps(v, (__m256*)&s, (__m256*)&c) ; return s/c; } - inline float_t log( const float_t& v ) { return log256_ps(v) ; } - inline float_t exp( const float_t& v ) { return exp256_ps(v) ; } - inline float_t abs ( const float_t& v ) { return v & _mm256_castsi256_ps( _mm256_set1_epi32( 0x7FFFFFFF ) ); } - inline float_t select(const float_t& mask, const float_t& a, const float_t& b ) { return _mm256_blendv_ps( b, a, mask ); } - inline float_t select(const bool& mask , const float_t& a, const float_t& b ) { return mask ? a : b; } - inline float_t atan2( const float_t& y, const float_t& x ){ - std::array bx{x.to_array()}, by{y.to_array()}, rt; - for( unsigned i = 0 ; i != 8 ; ++i ) rt[i] = std::atan2( by[i] , bx[i] ); - return float_t (rt.data() ); - } - inline float_t fmadd( const float_t& a, const float_t& b, const float_t& c ) - { - return _mm256_fmadd_ps(a, b, c ); - } - struct complex_t { - float_t re; - float_t im; - typedef std::complex scalar_type; - - float_t real() const { return re; } - float_t imag() const { return im; } - float_t norm() const { return re*re + im *im ; } - complex_t() = default; - complex_t( const float_t& re, const float_t& im) : re(re), im(im) {} - complex_t( const float& re, const float& im) : re(re), im(im) {} - complex_t( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} - complex_t( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} - const std::complex at(const unsigned i) const { return std::complex(re.to_array()[i], im.to_array()[i]) ; } - void store( float* sre, float* sim ){ re.store(sre); im.store(sim); } - void store( std::complex* r ){ - auto re_arr = re.to_array(); - auto im_arr = im.to_array(); - for( unsigned i = 0 ; i != re_arr.size(); ++i ) r[i] = std::complex( re_arr[i], im_arr[i] ); - } - }; - - inline std::ostream& operator<<( std::ostream& os, const float_t& obj ) { - auto buffer = obj.to_array(); - for( unsigned i = 0 ; i != 8; ++i ) os << buffer[i] << " "; - return os; - } - inline float_t real(const complex_t& arg ){ return arg.re ; } - inline float_t imag(const complex_t& arg ){ return arg.im ; } - inline complex_t conj(const complex_t& arg ){ return complex_t(arg.re, -arg.im) ; } - inline float_t conj(const float_t& arg ){ return arg ; } - inline complex_t operator+( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re + rhs, lhs.im); } - inline complex_t operator-( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re - rhs, lhs.im); } - inline complex_t operator*( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re*rhs, lhs.im*rhs); } - inline complex_t operator/( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re/rhs, lhs.im/rhs); } - inline complex_t operator+( const float_t& lhs, const complex_t& rhs ) { return complex_t(lhs + rhs.re, rhs.im); } - inline complex_t operator-( const float_t& lhs, const complex_t& rhs ) { return complex_t(lhs - rhs.re, - rhs.im); } - inline complex_t operator*( const float_t& lhs, const complex_t& rhs ) { return complex_t(lhs*rhs.re, lhs*rhs.im); } - inline complex_t operator/( const float_t& lhs, const complex_t& rhs ) { return complex_t( lhs * rhs.re , -lhs *rhs.im) / (rhs.re * rhs.re + rhs.im * rhs.im ); } - inline complex_t operator+( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re + rhs.re, lhs.im + rhs.im); } - inline complex_t operator-( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re - rhs.re, lhs.im - rhs.im); } - inline complex_t operator*( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re*rhs.re - lhs.im*rhs.im, lhs.re*rhs.im + lhs.im*rhs.re); } - inline complex_t operator/( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re*rhs.re + lhs.im*rhs.im, -lhs.re*rhs.im + lhs.im*rhs.re) / (rhs.re * rhs.re + rhs.im * rhs.im ); } - inline complex_t operator-( const complex_t& x ) { return -1.f * x; } - inline float_t abs( const complex_t& v ) { return sqrt( v.re * v.re + v.im * v.im ) ; } - inline float_t norm( const complex_t& v ) { return ( v.re * v.re + v.im * v.im ) ; } - inline complex_t select(const float_t& mask, const complex_t& a, const complex_t& b ) { return complex_t( _mm256_blendv_ps( b.re, a.re, mask ), _mm256_blendv_ps( b.im, a.im, mask ) ); } - inline complex_t select(const float_t& mask, const float_t& a, const complex_t& b ) { return complex_t( _mm256_blendv_ps( b.re, a , mask ), _mm256_blendv_ps( b.im, float_t(0.f), mask ) ); } - inline complex_t select(const float_t& mask, const complex_t& a, const float_t& b ) { return complex_t( _mm256_blendv_ps( b, a.re, mask ), _mm256_blendv_ps( float_t(0.f), a.im, mask ) ); } - inline complex_t select(const bool& mask , const complex_t& a, const complex_t& b ) { return mask ? a : b; } - inline complex_t exp( const complex_t& v ){ - float_t s; float_t c; sincos256_ps(v.im, (__m256*)&s, (__m256*)&c) ; - return exp( v.re ) * complex_t(c, s); - } - inline std::ostream& operator<<( std::ostream& os, const complex_t& obj ) { return os << "( "<< obj.re << ") (" << obj.im << ")"; } - #pragma omp declare reduction(+: float_t: \ - omp_out = omp_out + omp_in) - #pragma omp declare reduction(+: complex_t: \ - omp_out = omp_out + omp_in) - - } -} - -#endif diff --git a/AmpGen/simd/avx2d_types.h b/AmpGen/simd/avx2d_types.h index 5ed64e3101e..f478f365d6f 100644 --- a/AmpGen/simd/avx2d_types.h +++ b/AmpGen/simd/avx2d_types.h @@ -10,100 +10,101 @@ namespace AmpGen { namespace AVX2d { #define stl_fallback( x ) \ - inline float_t x( const float_t& v ){ auto a = v.to_array(); return float_t( std::x(a[0]), std::x(a[1]), std::x(a[2]), std::x(a[3]) ) ; } + inline real_v x( const real_v& v ){ auto a = v.to_array(); return real_v( std::x(a[0]), std::x(a[1]), std::x(a[2]), std::x(a[3]) ) ; } - struct float_t { + struct real_v { __m256d data; static constexpr unsigned size = 4; typedef double scalar_type; - float_t() = default; - float_t(__m256d data ) : data(data) {} - float_t(const double& f ) : data( _mm256_set1_pd( f )) {} - float_t(const double& x0, const double& x1, const double& x2, const double& x3 ) + real_v() = default; + real_v(__m256d data ) : data(data) {} + real_v(const double& f ) : data( _mm256_set1_pd( f )) {} + real_v(const double& x0, const double& x1, const double& x2, const double& x3 ) { double tmp[4] = {x0,x1,x2,x3}; data = _mm256_loadu_pd(tmp); } - float_t(const double* f ) : data( _mm256_loadu_pd( f ) ) {} + real_v(const double* f ) : data( _mm256_loadu_pd( f ) ) {} void store( double* ptr ) const { _mm256_storeu_pd( ptr, data ); } std::array to_array() const { std::array b; store( &b[0] ); return b; } double at(const unsigned i) const { return to_array()[i] ; } operator __m256d() const { return data ; } }; - inline float_t operator+( const float_t& lhs, const float_t& rhs ) { return _mm256_add_pd(lhs, rhs); } - inline float_t operator-( const float_t& lhs, const float_t& rhs ) { return _mm256_sub_pd(lhs, rhs); } - inline float_t operator*( const float_t& lhs, const float_t& rhs ) { return _mm256_mul_pd(lhs, rhs); } - inline float_t operator/( const float_t& lhs, const float_t& rhs ) { return _mm256_div_pd(lhs, rhs); } - inline float_t operator-( const float_t& x ) { return -1.f * x; } - inline float_t operator&( const float_t& lhs, const float_t& rhs ) { return _mm256_and_pd( lhs, rhs ); } - inline float_t operator|( const float_t& lhs, const float_t& rhs ) { return _mm256_or_pd( lhs, rhs ); } - inline float_t operator^( const float_t& lhs, const float_t& rhs ) { return _mm256_xor_pd( lhs, rhs ); } - inline float_t operator+=(float_t& lhs, const float_t& rhs ){ lhs = lhs + rhs; return lhs; } - inline float_t operator-=(float_t& lhs, const float_t& rhs ){ lhs = lhs - rhs; return lhs; } - inline float_t operator*=(float_t& lhs, const float_t& rhs ){ lhs = lhs * rhs; return lhs; } - inline float_t operator/=(float_t& lhs, const float_t& rhs ){ lhs = lhs / rhs; return lhs; } - inline float_t operator&&( const float_t& lhs, const float_t& rhs ) { return _mm256_and_pd( lhs, rhs ); } - inline float_t operator||( const float_t& lhs, const float_t& rhs ) { return _mm256_or_pd( lhs, rhs ); } - inline float_t operator!( const float_t& x ) { return x ^ _mm256_castsi256_pd( _mm256_set1_epi32( -1 ) ); } - inline float_t operator<( const float_t& lhs, const float_t& rhs ) { return _mm256_cmp_pd( lhs, rhs, _CMP_LT_OS ); } - inline float_t operator>( const float_t& lhs, const float_t& rhs ) { return _mm256_cmp_pd( lhs, rhs, _CMP_GT_OS ); } - inline float_t operator==( const float_t& lhs, const float_t& rhs ){ return _mm256_cmp_pd( lhs, rhs, _CMP_EQ_OS ); } - inline float_t sqrt( const float_t& v ) { return _mm256_sqrt_pd(v); } - inline float_t abs ( const float_t& v ) { return _mm256_andnot_pd(_mm256_set1_pd(-0.), v); } - // inline float_t sin( const float_t& v ) { return sin256_pd(v) ; } - // inline float_t cos( const float_t& v ) { return cos256_pd(v) ; } - // inline float_t tan( const float_t& v ) { float_t s; float_t c; sincos256_pd(v, (__m256*)&s, (__m256*)&c) ; return s/c; } - // inline float_t exp( const float_t& v ) { return exp256_ps(v) ; } - inline float_t select(const float_t& mask, const float_t& a, const float_t& b ) { return _mm256_blendv_pd( b, a, mask ); } - inline float_t select(const bool& mask , const float_t& a, const float_t& b ) { return mask ? a : b; } - inline float_t sign ( const float_t& v){ return select( v > 0., +1., -1. ); } - inline float_t atan2( const float_t& y, const float_t& x ){ + inline real_v operator+( const real_v& lhs, const real_v& rhs ) { return _mm256_add_pd(lhs, rhs); } + inline real_v operator-( const real_v& lhs, const real_v& rhs ) { return _mm256_sub_pd(lhs, rhs); } + inline real_v operator*( const real_v& lhs, const real_v& rhs ) { return _mm256_mul_pd(lhs, rhs); } + inline real_v operator/( const real_v& lhs, const real_v& rhs ) { return _mm256_div_pd(lhs, rhs); } + inline real_v operator-( const real_v& x ) { return -1.f * x; } + inline real_v operator&( const real_v& lhs, const real_v& rhs ) { return _mm256_and_pd( lhs, rhs ); } + inline real_v operator|( const real_v& lhs, const real_v& rhs ) { return _mm256_or_pd( lhs, rhs ); } + inline real_v operator^( const real_v& lhs, const real_v& rhs ) { return _mm256_xor_pd( lhs, rhs ); } + inline real_v operator+=(real_v& lhs, const real_v& rhs ){ lhs = lhs + rhs; return lhs; } + inline real_v operator-=(real_v& lhs, const real_v& rhs ){ lhs = lhs - rhs; return lhs; } + inline real_v operator*=(real_v& lhs, const real_v& rhs ){ lhs = lhs * rhs; return lhs; } + inline real_v operator/=(real_v& lhs, const real_v& rhs ){ lhs = lhs / rhs; return lhs; } + inline real_v operator&&( const real_v& lhs, const real_v& rhs ) { return _mm256_and_pd( lhs, rhs ); } + inline real_v operator||( const real_v& lhs, const real_v& rhs ) { return _mm256_or_pd( lhs, rhs ); } + inline real_v operator!( const real_v& x ) { return x ^ _mm256_castsi256_pd( _mm256_set1_epi32( -1 ) ); } + inline real_v operator<( const real_v& lhs, const real_v& rhs ) { return _mm256_cmp_pd( lhs, rhs, _CMP_LT_OS ); } + inline real_v operator>( const real_v& lhs, const real_v& rhs ) { return _mm256_cmp_pd( lhs, rhs, _CMP_GT_OS ); } + inline real_v operator==( const real_v& lhs, const real_v& rhs ){ return _mm256_cmp_pd( lhs, rhs, _CMP_EQ_OS ); } + inline real_v sqrt( const real_v& v ) { return _mm256_sqrt_pd(v); } + inline real_v abs ( const real_v& v ) { return _mm256_andnot_pd(_mm256_set1_pd(-0.), v); } + // inline real_v sin( const real_v& v ) { return sin256_pd(v) ; } + // inline real_v cos( const real_v& v ) { return cos256_pd(v) ; } + // inline real_v tan( const real_v& v ) { real_v s; real_v c; sincos256_pd(v, (__m256*)&s, (__m256*)&c) ; return s/c; } + // inline real_v exp( const real_v& v ) { return exp256_ps(v) ; } + inline real_v select(const real_v& mask, const real_v& a, const real_v& b ) { return _mm256_blendv_pd( b, a, mask ); } + inline real_v select(const bool& mask , const real_v& a, const real_v& b ) { return mask ? a : b; } + inline real_v sign ( const real_v& v){ return select( v > 0., +1., -1. ); } + inline real_v atan2( const real_v& y, const real_v& x ){ std::array bx{x.to_array()}, by{y.to_array()}; - return float_t ( + return real_v ( std::atan2( by[0], bx[0]) , std::atan2( by[1], bx[1]) , std::atan2( by[2], bx[2]) , std::atan2( by[3], bx[3]) ); } - inline __m256i double_to_int( const float_t& x ) + inline __m256i udouble_to_uint( const real_v& x ) { + auto xr = _mm256_round_pd(x, _MM_FROUND_TO_NEG_INF); // based on: https://stackoverflow.com/questions/41144668/how-to-efficiently-perform-double-int64-conversions-with-sse-avx - return _mm256_sub_epi64(_mm256_castpd_si256(_mm256_add_pd(x, _mm256_set1_pd(0x0018000000000000))), + return _mm256_sub_epi64(_mm256_castpd_si256(_mm256_add_pd(xr, _mm256_set1_pd(0x0018000000000000))), _mm256_castpd_si256(_mm256_set1_pd(0x0018000000000000))); } - inline float_t gather( const double* base_addr, const float_t& offsets) + inline real_v gather( const double* base_addr, const real_v& offsets) { - return _mm256_i64gather_pd(base_addr, double_to_int(offsets),sizeof(double)); + return _mm256_i64gather_pd(base_addr, udouble_to_uint(offsets),sizeof(double)); } - inline void frexp(const AVX2d::float_t& value, AVX2d::float_t& mant, AVX2d::float_t& exponent) + inline void frexp(const real_v& value, real_v& mant, real_v& exponent) { auto arg_as_int = _mm256_castpd_si256(value); - static const AVX2d::float_t offset(4503599627370496.0 + 1022.0); // 2^52 + 1022.0 + static const real_v offset(4503599627370496.0 + 1022.0); // 2^52 + 1022.0 static const __m256i pow2_52_i = _mm256_set1_epi64x(0x4330000000000000); // *reinterpret_cast(&pow2_52_d); auto b = _mm256_srl_epi64(arg_as_int, _mm_cvtsi32_si128(52)); auto c = _mm256_or_si256( b , pow2_52_i); - exponent = AVX2d::float_t( _mm256_castsi256_pd(c) ) - offset; + exponent = real_v( _mm256_castsi256_pd(c) ) - offset; mant = _mm256_castsi256_pd(_mm256_or_si256(_mm256_and_si256 (arg_as_int, _mm256_set1_epi64x(0x000FFFFFFFFFFFFFll) ), _mm256_set1_epi64x(0x3FE0000000000000ll))); } - inline float_t fmadd( const float_t& a, const float_t& b, const float_t& c ) + inline real_v fmadd( const real_v& a, const real_v& b, const real_v& c ) { return _mm256_fmadd_pd(a, b, c); } - inline float_t log(const AVX2d::float_t& arg) + inline real_v log(const real_v& arg) { - static const AVX2d::float_t corr = 0.693147180559945286226764; - static const AVX2d::float_t CL15 = 0.148197055177935105296783; - static const AVX2d::float_t CL13 = 0.153108178020442575739679; - static const AVX2d::float_t CL11 = 0.181837339521549679055568; - static const AVX2d::float_t CL9 = 0.22222194152736701733275; - static const AVX2d::float_t CL7 = 0.285714288030134544449368; - static const AVX2d::float_t CL5 = 0.399999999989941956712869; - static const AVX2d::float_t CL3 = 0.666666666666685503450651; - static const AVX2d::float_t CL1 = 2.0; - AVX2d::float_t mant, exponent; + static const real_v corr = 0.693147180559945286226764; + static const real_v CL15 = 0.148197055177935105296783; + static const real_v CL13 = 0.153108178020442575739679; + static const real_v CL11 = 0.181837339521549679055568; + static const real_v CL9 = 0.22222194152736701733275; + static const real_v CL7 = 0.285714288030134544449368; + static const real_v CL5 = 0.399999999989941956712869; + static const real_v CL3 = 0.666666666666685503450651; + static const real_v CL1 = 2.0; + real_v mant, exponent; frexp(arg, mant, exponent); auto x = (mant - 1.) / (mant + 1.); auto x2 = x * x; @@ -121,26 +122,29 @@ namespace AmpGen { stl_fallback( tan ) stl_fallback( sin ) stl_fallback( cos ) - inline float_t remainder( const float_t& a, const float_t& b ){ return a - float_t(_mm256_round_pd(a/b, _MM_FROUND_TO_NEG_INF)) * b; } - inline float_t fmod( const float_t& a, const float_t& b ) + inline real_v remainder( const real_v& a, const real_v& b ){ return a - real_v(_mm256_round_pd(a/b, _MM_FROUND_TO_NEG_INF)) * b; } + inline real_v fmod( const real_v& a, const real_v& b ) { auto r = remainder( abs(a), abs(b) ); return select( a > 0., r, -r ); } - struct complex_t { - float_t re; - float_t im; + struct complex_v { + real_v re; + real_v im; typedef std::complex scalar_type; + static constexpr unsigned size = 4; - float_t real() const { return re; } - float_t imag() const { return im; } - float_t norm() const { return re*re + im *im ; } - complex_t() = default; - complex_t( const float_t& re, const float_t& im) : re(re), im(im) {} - complex_t( const float& re, const float& im) : re(re), im(im) {} - complex_t( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} - complex_t( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} + real_v real() const { return re; } + real_v imag() const { return im; } + real_v norm() const { return re*re + im *im ; } + complex_v() = default; + complex_v( const real_v& re, const real_v& im) : re(re), im(im) {} + complex_v( const float& re, const float& im) : re(re), im(im) {} + complex_v( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} + complex_v( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} + explicit complex_v( const real_v& arg ) : re(arg) {}; + explicit complex_v( const double& arg ) : re(arg) {}; const std::complex at(const unsigned i) const { return std::complex(re.to_array()[i], im.to_array()[i]) ; } void store( double* sre, double* sim ){ re.store(sre); im.store(sim); } void store( scalar_type* r ) const { @@ -156,51 +160,51 @@ namespace AmpGen { } }; - inline std::ostream& operator<<( std::ostream& os, const float_t& obj ) { + inline std::ostream& operator<<( std::ostream& os, const real_v& obj ) { auto buffer = obj.to_array(); for( unsigned i = 0 ; i != 4; ++i ) os << buffer[i] << " "; return os; } - inline float_t real(const complex_t& arg ){ return arg.re ; } - inline float_t imag(const complex_t& arg ){ return arg.im ; } - inline complex_t conj(const complex_t& arg ){ return complex_t(arg.re, -arg.im) ; } - inline float_t conj(const float_t& arg ){ return arg ; } - inline complex_t operator+( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re + rhs, lhs.im); } - inline complex_t operator-( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re - rhs, lhs.im); } - inline complex_t operator*( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re*rhs, lhs.im*rhs); } - inline complex_t operator/( const complex_t& lhs, const float_t& rhs ) { return complex_t(lhs.re/rhs, lhs.im/rhs); } - inline complex_t operator+( const float_t& lhs, const complex_t& rhs ) { return complex_t(lhs + rhs.re, rhs.im); } - inline complex_t operator-( const float_t& lhs, const complex_t& rhs ) { return complex_t(lhs - rhs.re, - rhs.im); } - inline complex_t operator*( const float_t& lhs, const complex_t& rhs ) { return complex_t(lhs*rhs.re, lhs*rhs.im); } - inline complex_t operator/( const float_t& lhs, const complex_t& rhs ) { return complex_t( lhs * rhs.re , -lhs *rhs.im) / (rhs.re * rhs.re + rhs.im * rhs.im ); } - inline complex_t operator+( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re + rhs.re, lhs.im + rhs.im); } - inline complex_t operator-( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re - rhs.re, lhs.im - rhs.im); } - inline complex_t operator*( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re*rhs.re - lhs.im*rhs.im, lhs.re*rhs.im + lhs.im*rhs.re); } - inline complex_t operator/( const complex_t& lhs, const complex_t& rhs ) { return complex_t(lhs.re*rhs.re + lhs.im*rhs.im, -lhs.re*rhs.im + lhs.im*rhs.re) / (rhs.re * rhs.re + rhs.im * rhs.im ); } - inline complex_t operator-( const complex_t& x ) { return -1.f * x; } - inline float_t abs( const complex_t& v ) { return sqrt( v.re * v.re + v.im * v.im ) ; } - inline float_t norm( const complex_t& v ) { return ( v.re * v.re + v.im * v.im ) ; } - inline complex_t select(const float_t& mask, const complex_t& a, const complex_t& b ) { return complex_t( select(mask, a.re, b.re), select(mask, a.im, b.im ) ) ; } - inline complex_t select(const float_t& mask, const float_t& a, const complex_t& b ) { return complex_t( select(mask, a , b.re), select(mask, 0.f, b.im) ); } - inline complex_t select(const float_t& mask, const complex_t& a, const float_t& b ) { return complex_t( select(mask, a.re, b ) , select(mask, a.im, 0.f) ); } - inline complex_t select(const bool& mask , const complex_t& a, const complex_t& b ) { return mask ? a : b; } - inline complex_t exp( const complex_t& v ){ - return exp( v.re) * complex_t( cos( v.im ), sin( v.im ) ); + inline real_v real(const complex_v& arg ){ return arg.re ; } + inline real_v imag(const complex_v& arg ){ return arg.im ; } + inline complex_v conj(const complex_v& arg ){ return complex_v(arg.re, -arg.im) ; } + inline real_v conj(const real_v& arg ){ return arg ; } + inline complex_v operator+( const complex_v& lhs, const real_v& rhs ) { return complex_v(lhs.re + rhs, lhs.im); } + inline complex_v operator-( const complex_v& lhs, const real_v& rhs ) { return complex_v(lhs.re - rhs, lhs.im); } + inline complex_v operator*( const complex_v& lhs, const real_v& rhs ) { return complex_v(lhs.re*rhs, lhs.im*rhs); } + inline complex_v operator/( const complex_v& lhs, const real_v& rhs ) { return complex_v(lhs.re/rhs, lhs.im/rhs); } + inline complex_v operator+( const real_v& lhs, const complex_v& rhs ) { return complex_v(lhs + rhs.re, rhs.im); } + inline complex_v operator-( const real_v& lhs, const complex_v& rhs ) { return complex_v(lhs - rhs.re, - rhs.im); } + inline complex_v operator*( const real_v& lhs, const complex_v& rhs ) { return complex_v(lhs*rhs.re, lhs*rhs.im); } + inline complex_v operator/( const real_v& lhs, const complex_v& rhs ) { return complex_v( lhs * rhs.re , -lhs *rhs.im) / (rhs.re * rhs.re + rhs.im * rhs.im ); } + inline complex_v operator+( const complex_v& lhs, const complex_v& rhs ) { return complex_v(lhs.re + rhs.re, lhs.im + rhs.im); } + inline complex_v operator-( const complex_v& lhs, const complex_v& rhs ) { return complex_v(lhs.re - rhs.re, lhs.im - rhs.im); } + inline complex_v operator*( const complex_v& lhs, const complex_v& rhs ) { return complex_v(lhs.re*rhs.re - lhs.im*rhs.im, lhs.re*rhs.im + lhs.im*rhs.re); } + inline complex_v operator/( const complex_v& lhs, const complex_v& rhs ) { return complex_v(lhs.re*rhs.re + lhs.im*rhs.im, -lhs.re*rhs.im + lhs.im*rhs.re) / (rhs.re * rhs.re + rhs.im * rhs.im ); } + inline complex_v operator-( const complex_v& x ) { return -1.f * x; } + inline real_v abs( const complex_v& v ) { return sqrt( v.re * v.re + v.im * v.im ) ; } + inline real_v norm( const complex_v& v ) { return ( v.re * v.re + v.im * v.im ) ; } + inline complex_v select(const real_v& mask, const complex_v& a, const complex_v& b ) { return complex_v( select(mask, a.re, b.re), select(mask, a.im, b.im ) ) ; } + inline complex_v select(const real_v& mask, const real_v& a, const complex_v& b ) { return complex_v( select(mask, a , b.re), select(mask, 0.f, b.im) ); } + inline complex_v select(const real_v& mask, const complex_v& a, const real_v& b ) { return complex_v( select(mask, a.re, b ) , select(mask, a.im, 0.f) ); } + inline complex_v select(const bool& mask , const complex_v& a, const complex_v& b ) { return mask ? a : b; } + inline complex_v exp( const complex_v& v ){ + return exp( v.re) * complex_v( cos( v.im ), sin( v.im ) ); } - inline complex_t sqrt( const complex_t& v ) + inline complex_v sqrt( const complex_v& v ) { auto r = abs(v); - return complex_t ( sqrt( 0.5 * (r + v.re) ), sign(v.im) * sqrt( 0.5*( r - v.re ) ) ); + return complex_v ( sqrt( 0.5 * (r + v.re) ), sign(v.im) * sqrt( 0.5*( r - v.re ) ) ); } - inline complex_t log( const complex_t& v ) + inline complex_v log( const complex_v& v ) { - return complex_t( log( v.re ) , atan2(v.im, v.re) ); + return complex_v( log( v.re ) , atan2(v.im, v.re) ); } - inline std::ostream& operator<<( std::ostream& os, const complex_t& obj ) { return os << "( "<< obj.re << ") (" << obj.im << ")"; } - #pragma omp declare reduction(+: float_t: \ + inline std::ostream& operator<<( std::ostream& os, const complex_v& obj ) { return os << "( "<< obj.re << ") (" << obj.im << ")"; } + #pragma omp declare reduction(+: real_v: \ omp_out = omp_out + omp_in) - #pragma omp declare reduction(+: complex_t: \ + #pragma omp declare reduction(+: complex_v: \ omp_out = omp_out + omp_in) } diff --git a/AmpGen/simd/avx2f_types.h b/AmpGen/simd/avx2f_types.h new file mode 100644 index 00000000000..6ddd78327fd --- /dev/null +++ b/AmpGen/simd/avx2f_types.h @@ -0,0 +1,128 @@ +#ifndef AMPGEN_AVX_TYPES +#define AMPGEN_AVX_TYPES 1 + +#include +#include +#include +#include +#include "AmpGen/simd/avx_mathfun.h" +#include + +namespace AmpGen { + namespace AVX2 { + struct real_v { + __m256 data; + static constexpr unsigned size = 8 ; + typedef float scalar_type; + real_v() = default; + real_v(__m256 data ) : data(data) {} + real_v(const float& f ) : data( _mm256_set1_ps(f) ) {} + real_v(const double& f ) : data( _mm256_set1_ps( float(f) )) {} + real_v(const float* f ) : data( _mm256_loadu_ps( f ) ) {} + void store( float* ptr ) const { _mm256_storeu_ps( ptr, data ); } + std::array to_array() const { std::array b; store( &b[0] ); return b; } + float at(const unsigned i) const { return to_array()[i] ; } + operator __m256() const { return data ; } + }; + + inline real_v operator+( const real_v& lhs, const real_v& rhs ) { return _mm256_add_ps(lhs, rhs); } + inline real_v operator-( const real_v& lhs, const real_v& rhs ) { return _mm256_sub_ps(lhs, rhs); } + inline real_v operator*( const real_v& lhs, const real_v& rhs ) { return _mm256_mul_ps(lhs, rhs); } + inline real_v operator/( const real_v& lhs, const real_v& rhs ) { return _mm256_div_ps(lhs, rhs); } + inline real_v operator-( const real_v& x ) { return -1.f * x; } + inline real_v operator&( const real_v& lhs, const real_v& rhs ) { return _mm256_and_ps( lhs, rhs ); } + inline real_v operator|( const real_v& lhs, const real_v& rhs ) { return _mm256_or_ps( lhs, rhs ); } + inline real_v operator^( const real_v& lhs, const real_v& rhs ) { return _mm256_xor_ps( lhs, rhs ); } + inline real_v operator+=(real_v& lhs, const real_v& rhs ){ lhs = lhs + rhs; return lhs; } + inline real_v operator-=(real_v& lhs, const real_v& rhs ){ lhs = lhs - rhs; return lhs; } + inline real_v operator*=(real_v& lhs, const real_v& rhs ){ lhs = lhs * rhs; return lhs; } + inline real_v operator/=(real_v& lhs, const real_v& rhs ){ lhs = lhs / rhs; return lhs; } + inline real_v operator&&( const real_v& lhs, const real_v& rhs ) { return _mm256_and_ps( lhs, rhs ); } + inline real_v operator||( const real_v& lhs, const real_v& rhs ) { return _mm256_or_ps( lhs, rhs ); } + inline real_v operator!( const real_v& x ) { return x ^ _mm256_castsi256_ps( _mm256_set1_epi32( -1 ) ); } + inline real_v operator<( const real_v& lhs, const real_v& rhs ) { return _mm256_cmp_ps( lhs, rhs, _CMP_LT_OS ); } + inline real_v operator>( const real_v& lhs, const real_v& rhs ) { return _mm256_cmp_ps( lhs, rhs, _CMP_GT_OS ); } + inline real_v operator==( const real_v& lhs, const real_v& rhs ){ return _mm256_cmp_ps( lhs, rhs, _CMP_EQ_OS ); } + inline real_v sqrt( const real_v& v ) { return _mm256_sqrt_ps(v); } + inline real_v sin( const real_v& v ) { return sin256_ps(v) ; } + inline real_v cos( const real_v& v ) { return cos256_ps(v) ; } + inline real_v tan( const real_v& v ) { real_v s; real_v c; sincos256_ps(v, (__m256*)&s, (__m256*)&c) ; return s/c; } + inline real_v log( const real_v& v ) { return log256_ps(v) ; } + inline real_v exp( const real_v& v ) { return exp256_ps(v) ; } + inline real_v abs ( const real_v& v ) { return v & _mm256_castsi256_ps( _mm256_set1_epi32( 0x7FFFFFFF ) ); } + inline real_v select(const real_v& mask, const real_v& a, const real_v& b ) { return _mm256_blendv_ps( b, a, mask ); } + inline real_v select(const bool& mask , const real_v& a, const real_v& b ) { return mask ? a : b; } + inline real_v atan2( const real_v& y, const real_v& x ){ + std::array bx{x.to_array()}, by{y.to_array()}, rt; + for( unsigned i = 0 ; i != 8 ; ++i ) rt[i] = std::atan2( by[i] , bx[i] ); + return real_v (rt.data() ); + } + inline real_v fmadd( const real_v& a, const real_v& b, const real_v& c ) + { + return _mm256_fmadd_ps(a, b, c ); + } + struct complex_v { + real_v re; + real_v im; + typedef std::complex scalar_type; + static constexpr unsigned size = 8 ; + + real_v real() const { return re; } + real_v imag() const { return im; } + real_v norm() const { return re*re + im *im ; } + complex_v() = default; + complex_v( const real_v& re, const real_v& im) : re(re), im(im) {} + complex_v( const float& re, const float& im) : re(re), im(im) {} + complex_v( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} + complex_v( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} + const std::complex at(const unsigned i) const { return std::complex(re.to_array()[i], im.to_array()[i]) ; } + void store( float* sre, float* sim ){ re.store(sre); im.store(sim); } + void store( std::complex* r ){ + auto re_arr = re.to_array(); + auto im_arr = im.to_array(); + for( unsigned i = 0 ; i != re_arr.size(); ++i ) r[i] = std::complex( re_arr[i], im_arr[i] ); + } + }; + + inline std::ostream& operator<<( std::ostream& os, const real_v& obj ) { + auto buffer = obj.to_array(); + for( unsigned i = 0 ; i != 8; ++i ) os << buffer[i] << " "; + return os; + } + inline real_v real(const complex_v& arg ){ return arg.re ; } + inline real_v imag(const complex_v& arg ){ return arg.im ; } + inline complex_v conj(const complex_v& arg ){ return complex_v(arg.re, -arg.im) ; } + inline real_v conj(const real_v& arg ){ return arg ; } + inline complex_v operator+( const complex_v& lhs, const real_v& rhs ) { return complex_v(lhs.re + rhs, lhs.im); } + inline complex_v operator-( const complex_v& lhs, const real_v& rhs ) { return complex_v(lhs.re - rhs, lhs.im); } + inline complex_v operator*( const complex_v& lhs, const real_v& rhs ) { return complex_v(lhs.re*rhs, lhs.im*rhs); } + inline complex_v operator/( const complex_v& lhs, const real_v& rhs ) { return complex_v(lhs.re/rhs, lhs.im/rhs); } + inline complex_v operator+( const real_v& lhs, const complex_v& rhs ) { return complex_v(lhs + rhs.re, rhs.im); } + inline complex_v operator-( const real_v& lhs, const complex_v& rhs ) { return complex_v(lhs - rhs.re, - rhs.im); } + inline complex_v operator*( const real_v& lhs, const complex_v& rhs ) { return complex_v(lhs*rhs.re, lhs*rhs.im); } + inline complex_v operator/( const real_v& lhs, const complex_v& rhs ) { return complex_v( lhs * rhs.re , -lhs *rhs.im) / (rhs.re * rhs.re + rhs.im * rhs.im ); } + inline complex_v operator+( const complex_v& lhs, const complex_v& rhs ) { return complex_v(lhs.re + rhs.re, lhs.im + rhs.im); } + inline complex_v operator-( const complex_v& lhs, const complex_v& rhs ) { return complex_v(lhs.re - rhs.re, lhs.im - rhs.im); } + inline complex_v operator*( const complex_v& lhs, const complex_v& rhs ) { return complex_v(lhs.re*rhs.re - lhs.im*rhs.im, lhs.re*rhs.im + lhs.im*rhs.re); } + inline complex_v operator/( const complex_v& lhs, const complex_v& rhs ) { return complex_v(lhs.re*rhs.re + lhs.im*rhs.im, -lhs.re*rhs.im + lhs.im*rhs.re) / (rhs.re * rhs.re + rhs.im * rhs.im ); } + inline complex_v operator-( const complex_v& x ) { return -1.f * x; } + inline real_v abs( const complex_v& v ) { return sqrt( v.re * v.re + v.im * v.im ) ; } + inline real_v norm( const complex_v& v ) { return ( v.re * v.re + v.im * v.im ) ; } + inline complex_v select(const real_v& mask, const complex_v& a, const complex_v& b ) { return complex_v( _mm256_blendv_ps( b.re, a.re, mask ), _mm256_blendv_ps( b.im, a.im, mask ) ); } + inline complex_v select(const real_v& mask, const real_v& a, const complex_v& b ) { return complex_v( _mm256_blendv_ps( b.re, a , mask ), _mm256_blendv_ps( b.im, real_v(0.f), mask ) ); } + inline complex_v select(const real_v& mask, const complex_v& a, const real_v& b ) { return complex_v( _mm256_blendv_ps( b, a.re, mask ), _mm256_blendv_ps( real_v(0.f), a.im, mask ) ); } + inline complex_v select(const bool& mask , const complex_v& a, const complex_v& b ) { return mask ? a : b; } + inline complex_v exp( const complex_v& v ){ + real_v s; real_v c; sincos256_ps(v.im, (__m256*)&s, (__m256*)&c) ; + return exp( v.re ) * complex_v(c, s); + } + inline std::ostream& operator<<( std::ostream& os, const complex_v& obj ) { return os << "( "<< obj.re << ") (" << obj.im << ")"; } + #pragma omp declare reduction(+: real_v: \ + omp_out = omp_out + omp_in) + #pragma omp declare reduction(+: complex_v: \ + omp_out = omp_out + omp_in) + + } +} + +#endif diff --git a/AmpGen/simd/avx512d_types.h b/AmpGen/simd/avx512d_types.h new file mode 100644 index 00000000000..a43af591688 --- /dev/null +++ b/AmpGen/simd/avx512d_types.h @@ -0,0 +1,212 @@ +#ifndef AMPGEN_AVXd_TYPES +#define AMPGEN_AVXd_TYPES 1 + +#include +#include +#include +#include +#include + +namespace AmpGen { + namespace AVX512d { + #define stl_fallback( x ) \ + inline real_v x( const real_v& v ){ auto a = v.to_array(); return real_v( std::x(a[0]), std::x(a[1]), std::x(a[2]), std::x(a[3]), std::x(a[4]), std::x(a[5]), std::x(a[6]), std::x(a[7]) ) ; } + + struct real_v { + __m512d data; + static constexpr unsigned size = 8; + typedef double scalar_type; + real_v() = default; + real_v(__m512d data ) : data(data) {} + real_v(const double& f ) : data( _mm512_set1_pd( f )) {} + real_v( + const double& x0, const double& x1, const double& x2, const double& x3, + const double& x4, const double& x5, const double& x6, const double& x7) + { + double tmp[8] = {x0,x1,x2,x3,x4,x5,x6,x7}; + data = _mm512_loadu_pd(tmp); + } + real_v(const double* f ) : data( _mm512_loadu_pd( f ) ) {} + void store( double* ptr ) const { _mm512_storeu_pd( ptr, data ); } + std::array to_array() const { std::array b; store( &b[0] ); return b; } + double at(const unsigned i) const { return to_array()[i] ; } + operator __m512d() const { return data ; } + }; + + inline real_v operator+( const real_v& lhs, const real_v& rhs ) { return _mm512_add_pd(lhs, rhs); } + inline real_v operator-( const real_v& lhs, const real_v& rhs ) { return _mm512_sub_pd(lhs, rhs); } + inline real_v operator*( const real_v& lhs, const real_v& rhs ) { return _mm512_mul_pd(lhs, rhs); } + inline real_v operator/( const real_v& lhs, const real_v& rhs ) { return _mm512_div_pd(lhs, rhs); } + inline real_v operator-( const real_v& x ) { return -1.f * x; } + inline real_v operator&( const real_v& lhs, const real_v& rhs ) { return _mm512_and_pd( lhs, rhs ); } + inline real_v operator|( const real_v& lhs, const real_v& rhs ) { return _mm512_or_pd( lhs, rhs ); } + inline real_v operator^( const real_v& lhs, const real_v& rhs ) { return _mm512_xor_pd( lhs, rhs ); } + inline real_v operator+=(real_v& lhs, const real_v& rhs ){ lhs = lhs + rhs; return lhs; } + inline real_v operator-=(real_v& lhs, const real_v& rhs ){ lhs = lhs - rhs; return lhs; } + inline real_v operator*=(real_v& lhs, const real_v& rhs ){ lhs = lhs * rhs; return lhs; } + inline real_v operator/=(real_v& lhs, const real_v& rhs ){ lhs = lhs / rhs; return lhs; } + inline real_v operator&&( const real_v& lhs, const real_v& rhs ) { return _mm512_and_pd( lhs, rhs ); } + inline real_v operator||( const real_v& lhs, const real_v& rhs ) { return _mm512_or_pd( lhs, rhs ); } + inline real_v operator!( const real_v& x ) { return x ^ _mm512_castsi512_pd( _mm512_set1_epi32( -1 ) ); } + inline __mmask8 operator<( const real_v& lhs, const real_v& rhs ) { return _mm512_cmp_pd_mask( lhs, rhs, _CMP_LT_OS ); } + inline __mmask8 operator>( const real_v& lhs, const real_v& rhs ) { return _mm512_cmp_pd_mask( lhs, rhs, _CMP_GT_OS ); } + inline __mmask8 operator==( const real_v& lhs, const real_v& rhs ){ return _mm512_cmp_pd_mask( lhs, rhs, _CMP_EQ_OS ); } + inline real_v sqrt( const real_v& v ) { return _mm512_sqrt_pd(v); } + inline real_v abs ( const real_v& v ) { return _mm512_andnot_pd(_mm512_set1_pd(-0.), v); } + // inline real_v sin( const real_v& v ) { return sin512_pd(v) ; } + // inline real_v cos( const real_v& v ) { return cos512_pd(v) ; } + // inline real_v tan( const real_v& v ) { real_v s; real_v c; sincos512_pd(v, (__m512*)&s, (__m512*)&c) ; return s/c; } + // inline real_v exp( const real_v& v ) { return exp512_ps(v) ; } + inline real_v select(const __mmask8& mask, const real_v& a, const real_v& b ) { return _mm512_mask_mov_pd( b, mask, a ); } + inline real_v select(const bool& mask , const real_v& a, const real_v& b ) { return mask ? a : b; } + inline real_v sign ( const real_v& v){ return select( v > 0., +1., -1. ); } + inline real_v atan2( const real_v& y, const real_v& x ){ + std::array bx{x.to_array()}, by{y.to_array()}; + return real_v ( + std::atan2(by[0], bx[0]) , std::atan2( by[1], bx[1]), std::atan2( by[2], bx[2]), std::atan2( by[3], bx[3]) , + std::atan2(by[4], bx[4]) , std::atan2( by[5], bx[5]), std::atan2( by[6], bx[6]), std::atan2( by[7], bx[7]) ); + } + inline __m512i double_to_int( const real_v& x ) + { + auto xr = _mm512_roundscale_pd(x, _MM_FROUND_TO_ZERO); + // based on: https://stackoverflow.com/questions/41144668/how-to-efficiently-perform-double-int64-conversions-with-sse-avx + return _mm512_sub_epi64(_mm512_castpd_si512(_mm512_add_pd(xr, _mm512_set1_pd(0x0018000000000000))), + _mm512_castpd_si512(_mm512_set1_pd(0x0018000000000000))); + } + inline real_v gather( const double* base_addr, const real_v& offsets) + { + return _mm512_i64gather_pd(double_to_int(offsets), base_addr, sizeof(double)); + } + + inline void frexp(const real_v& value, real_v& mant, real_v& exponent) + { + auto arg_as_int = _mm512_castpd_si512(value); + static const real_v offset(4503599627370496.0 + 1022.0); // 2^52 + 1022.0 + static const __m512i pow2_52_i = _mm512_set1_epi64(0x4330000000000000); // *reinterpret_cast(&pow2_52_d); + auto b = _mm512_srl_epi64(arg_as_int, _mm_cvtsi32_si128(52)); + auto c = _mm512_or_si512( b , pow2_52_i); + exponent = real_v( _mm512_castsi512_pd(c) ) - offset; + mant = _mm512_castsi512_pd(_mm512_or_si512(_mm512_and_si512 (arg_as_int, _mm512_set1_epi64(0x000FFFFFFFFFFFFFll) ), _mm512_set1_epi64(0x3FE0000000000000ll))); + } + + inline real_v fmadd( const real_v& a, const real_v& b, const real_v& c ) + { + return _mm512_fmadd_pd(a, b, c); + } + inline real_v log(const real_v& arg) + { + static const real_v corr = 0.693147180559945286226764; + static const real_v CL15 = 0.148197055177935105296783; + static const real_v CL13 = 0.153108178020442575739679; + static const real_v CL11 = 0.181837339521549679055568; + static const real_v CL9 = 0.22222194152736701733275; + static const real_v CL7 = 0.285714288030134544449368; + static const real_v CL5 = 0.399999999989941956712869; + static const real_v CL3 = 0.666666666666685503450651; + static const real_v CL1 = 2.0; + real_v mant, exponent; + frexp(arg, mant, exponent); + auto x = (mant - 1.) / (mant + 1.); + auto x2 = x * x; + auto p = fmadd(CL15, x2, CL13); + p = fmadd(p, x2, CL11); + p = fmadd(p, x2, CL9); + p = fmadd(p, x2, CL7); + p = fmadd(p, x2, CL5); + p = fmadd(p, x2, CL3); + p = fmadd(p, x2, CL1); + p = fmadd(p, x, corr * exponent); + return p; + } + stl_fallback( exp ) + stl_fallback( tan ) + stl_fallback( sin ) + stl_fallback( cos ) + inline real_v remainder( const real_v& a, const real_v& b ){ return a - real_v(_mm512_roundscale_pd(a/b, _MM_FROUND_TO_NEG_INF)) * b; } + inline real_v fmod( const real_v& a, const real_v& b ) + { + auto r = remainder( abs(a), abs(b) ); + return select( a > 0., r, -r ); + } + + struct complex_v { + real_v re; + real_v im; + typedef std::complex scalar_type; + + real_v real() const { return re; } + real_v imag() const { return im; } + real_v norm() const { return re*re + im *im ; } + complex_v() = default; + complex_v( const real_v& re, const real_v& im) : re(re), im(im) {} + complex_v( const float& re, const float& im) : re(re), im(im) {} + complex_v( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} + complex_v( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} + explicit complex_v( const real_v& arg ) : re(arg) {}; + explicit complex_v( const double& arg ) : re(arg) {}; + const std::complex at(const unsigned i) const { return std::complex(re.to_array()[i], im.to_array()[i]) ; } + void store( double* sre, double* sim ){ re.store(sre); im.store(sim); } + void store( scalar_type* r ) const { + auto re_arr = re.to_array(); + auto im_arr = im.to_array(); + for( unsigned i = 0 ; i != re_arr.size(); ++i ) r[i] = scalar_type( re_arr[i], im_arr[i] ); + } + auto to_array() const + { + std::array rt; + store( rt.data() ); + return rt; + } + }; + + inline std::ostream& operator<<( std::ostream& os, const real_v& obj ) { + auto buffer = obj.to_array(); + for( unsigned i = 0 ; i != 8; ++i ) os << buffer[i] << " "; + return os; + } + inline real_v real(const complex_v& arg ){ return arg.re ; } + inline real_v imag(const complex_v& arg ){ return arg.im ; } + inline complex_v conj(const complex_v& arg ){ return complex_v(arg.re, -arg.im) ; } + inline real_v conj(const real_v& arg ){ return arg ; } + inline complex_v operator+( const complex_v& lhs, const real_v& rhs ) { return complex_v(lhs.re + rhs, lhs.im); } + inline complex_v operator-( const complex_v& lhs, const real_v& rhs ) { return complex_v(lhs.re - rhs, lhs.im); } + inline complex_v operator*( const complex_v& lhs, const real_v& rhs ) { return complex_v(lhs.re*rhs, lhs.im*rhs); } + inline complex_v operator/( const complex_v& lhs, const real_v& rhs ) { return complex_v(lhs.re/rhs, lhs.im/rhs); } + inline complex_v operator+( const real_v& lhs, const complex_v& rhs ) { return complex_v(lhs + rhs.re, rhs.im); } + inline complex_v operator-( const real_v& lhs, const complex_v& rhs ) { return complex_v(lhs - rhs.re, - rhs.im); } + inline complex_v operator*( const real_v& lhs, const complex_v& rhs ) { return complex_v(lhs*rhs.re, lhs*rhs.im); } + inline complex_v operator/( const real_v& lhs, const complex_v& rhs ) { return complex_v( lhs * rhs.re , -lhs *rhs.im) / (rhs.re * rhs.re + rhs.im * rhs.im ); } + inline complex_v operator+( const complex_v& lhs, const complex_v& rhs ) { return complex_v(lhs.re + rhs.re, lhs.im + rhs.im); } + inline complex_v operator-( const complex_v& lhs, const complex_v& rhs ) { return complex_v(lhs.re - rhs.re, lhs.im - rhs.im); } + inline complex_v operator*( const complex_v& lhs, const complex_v& rhs ) { return complex_v(lhs.re*rhs.re - lhs.im*rhs.im, lhs.re*rhs.im + lhs.im*rhs.re); } + inline complex_v operator/( const complex_v& lhs, const complex_v& rhs ) { return complex_v(lhs.re*rhs.re + lhs.im*rhs.im, -lhs.re*rhs.im + lhs.im*rhs.re) / (rhs.re * rhs.re + rhs.im * rhs.im ); } + inline complex_v operator-( const complex_v& x ) { return -1.f * x; } + inline real_v abs( const complex_v& v ) { return sqrt( v.re * v.re + v.im * v.im ) ; } + inline real_v norm( const complex_v& v ) { return ( v.re * v.re + v.im * v.im ) ; } + inline complex_v select(const __mmask8& mask, const complex_v& a, const complex_v& b ) { return complex_v( select(mask, a.re, b.re), select(mask, a.im, b.im ) ) ; } + inline complex_v select(const __mmask8& mask, const real_v& a, const complex_v& b ) { return complex_v( select(mask, a , b.re), select(mask, 0.f, b.im) ); } + inline complex_v select(const __mmask8& mask, const complex_v& a, const real_v& b ) { return complex_v( select(mask, a.re, b ) , select(mask, a.im, 0.f) ); } + inline complex_v select(const bool& mask , const complex_v& a, const complex_v& b ) { return mask ? a : b; } + inline complex_v exp( const complex_v& v ){ + return exp( v.re) * complex_v( cos( v.im ), sin( v.im ) ); + } + inline complex_v sqrt( const complex_v& v ) + { + auto r = abs(v); + return complex_v ( sqrt( 0.5 * (r + v.re) ), sign(v.im) * sqrt( 0.5*( r - v.re ) ) ); + } + inline complex_v log( const complex_v& v ) + { + return complex_v( log( v.re ) , atan2(v.im, v.re) ); + } + + inline std::ostream& operator<<( std::ostream& os, const complex_v& obj ) { return os << "( "<< obj.re << ") (" << obj.im << ")"; } + #pragma omp declare reduction(+: real_v: \ + omp_out = omp_out + omp_in) + #pragma omp declare reduction(+: complex_v: \ + omp_out = omp_out + omp_in) + + } +} + +#endif diff --git a/AmpGen/simd/utils.h b/AmpGen/simd/utils.h index 62099046210..b10b3580c6c 100644 --- a/AmpGen/simd/utils.h +++ b/AmpGen/simd/utils.h @@ -2,47 +2,41 @@ #define AMPGEN_SIMD_UTILS_H #include -#if ENABLE_AVX2 -#if DOUBLE_PRECISION + +#if ENABLE_AVX512 + #include "AmpGen/simd/avx512d_types.h" +#elif ENABLE_AVX2d #include "AmpGen/simd/avx2d_types.h" -#else - #include "AmpGen/simd/avx2_types.h" -#endif +#elif ENABLE_AVX2f + #include "AmpGen/simd/avx2f_types.h" #endif namespace AmpGen { -#if ENABLE_AVX2 -#if DOUBLE_PRECISION - using float_v = AVX2d::float_t; - using complex_v = AVX2d::complex_t; -#else - using float_v = AVX2::float_t; - using complex_v = AVX2::complex_t; +#if ENABLE_AVX512 + namespace AVX = AVX512d; +#elif ENABLE_AVX2d + namespace AVX = AVX2d; +#elif ENABLE_AVX2f + namespace AVX = AVX2f; #endif + +#if ENABLE_AVX + using float_v = AVX::real_v; + using complex_v = AVX::complex_v; #else - using float_v = double; - using complex_v = std::complex; + using float_v = double; + using complex_v = std::complex; #endif namespace utils { template struct is_vector_type : std::false_type {}; template struct size { static constexpr unsigned value = 1; } ; -#if ENABLE_AVX2 -#if DOUBLE_PRECISION - template <> struct is_vector_type : std::true_type {}; - template <> struct is_vector_type : std::true_type {}; - template <> struct size { static constexpr unsigned value = 4; }; - template <> struct size { static constexpr unsigned value = 4; }; -#else - template <> struct is_vector_type : std::true_type {}; - template <> struct is_vector_type : std::true_type {}; - template <> struct size { static constexpr unsigned value = 8; }; - template <> struct size { static constexpr unsigned value = 8; }; -#endif -#else - template <> struct is_vector_type : std::false_type {}; - template <> struct is_vector_type : std::false_type {}; +#if ENABLE_AVX + template <> struct is_vector_type : std::true_type {}; + template <> struct is_vector_type : std::true_type {}; + template <> struct size { static constexpr unsigned value = AVX::complex_v::size; }; + template <> struct size { static constexpr unsigned value = AVX::complex_v::size; }; #endif template simd_type gather( const container_type& container, const functor_type& functor, unsigned offset=0, typename simd_type::scalar_type df =0.) @@ -69,6 +63,15 @@ namespace AmpGen { } else return obj; } + template bool all_of( const simd_type& obj, const value_type& v ) + { + if constexpr( ! is_vector_type::value ) return obj == v; + else { + auto arr = obj.to_array(); + for( unsigned i = 0 ; i != size::value; ++i ) if( arr[i] != v ) return false; + return true; + } + } template auto get( vtype v ) { if constexpr ( is_vector_type::value ) return v.at(p); @@ -81,11 +84,8 @@ namespace AmpGen { } template auto norm( const ctype& v ) { - #if ENABLE_AVX2 && DOUBLE_PRECISION - if constexpr( is_vector_type::value ) return AVX2d::norm(v); - #endif - #if ENABLE_AVX2 && ! DOUBLE_PRECISION - if constexpr( is_vector_type::value ) return AVX2::norm(v); + #if ENABLE_AVX + if constexpr( is_vector_type::value ) return AVX::norm(v); #endif if constexpr( ! is_vector_type::value ) return std::norm(v); } diff --git a/Standalone.cmake b/Standalone.cmake index 600bb8314b7..254d52f89af 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -12,9 +12,8 @@ if( NOT "${CMAKE_CXX_STANDARD}" ) set(CMAKE_CXX_STANDARD 17) endif() -SET(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") -SET(ENABLE_AVX2 TRUE CACHE BOOL "ENABLE_AVX2") -SET(PRECISION "DOUBLE" CACHE STRING "PRECISION") +SET(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") +SET(USE_SIMD "AVX2d" CACHE STRING "USE_SIMD") set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -153,20 +152,26 @@ target_compile_options(AmpGen -Wno-unknown-pragmas $<$:-O3>) -if( ENABLE_AVX2 ) - if( "${PRECISION}" MATCHES "DOUBLE" ) - message(STATUS "Enabling AVX2 [double precision]") - target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX2=1" "DOUBLE_PRECISION=1") - elseif( "${PRECISION}" MATCHES "SINGLE" ) - message(STATUS "Enabling AVX2 [single precision]") - target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX2=1" "DOUBLE_PRECISION=0") - endif() +# if( NOT ${USE_SIMD} MATCHES "" ) + if ( ${USE_SIMD} MATCHES "AVX2d" ) + message(STATUS "Enabling AVX2 [double precision]") + target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=1" "ENABLE_AVX2d=1") + target_compile_options(AmpGen PUBLIC -march=native -ftree-vectorize -mavx2 -DHAVE_AVX2_INSTRUCTIONS) + elseif ( ${USE_SIMD} MATCHES "AVX2f" ) + message(STATUS "Enabling AVX2 [single precision]") + target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=1" "ENABLE_AVX2f=1") target_compile_options(AmpGen PUBLIC -march=native -ftree-vectorize -mavx2 -DHAVE_AVX2_INSTRUCTIONS) - if("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" OR - "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) + elseif ( ${USE_SIMD} MATCHES "AVX512d" ) + message(STATUS "Enabling AVX2 [double precision]") + target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=1" "ENABLE_AVX512=1") + target_compile_options(AmpGen PUBLIC -march=native -ftree-vectorize -mavx512f -DHAVE_AVX512_INSTRUCTIONS) + endif() + if("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) target_compile_options(AmpGen PUBLIC -mfma) endif() -endif() + # else() + # message("SIMD disabled, resorting to scalar build : ${USE_SIMD}") + # endif() if("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" ) target_link_libraries(AmpGen PUBLIC stdc++ ) diff --git a/apps/DataConverter.cpp b/apps/DataConverter.cpp index 11081dc2a08..438a1e4fbd1 100644 --- a/apps/DataConverter.cpp +++ b/apps/DataConverter.cpp @@ -36,11 +36,10 @@ void invertParity( Event& event, const size_t& nParticles=0) } } - int main( int argc, char* argv[] ) { OptionsParser::setArgs( argc, argv ); - std::string inputFilename = NamedParameter("Input" , "", "Input ROOT file" ); + std::string inputFilename = NamedParameter("Input" , "", "Input ROOT file(s)" ); std::string treeName = NamedParameter("Tree" , "", "Input ROOT tree." ); std::string outputFilename = NamedParameter("Output" , "", "Output ROOT file" ); std::string pdfLibrary = NamedParameter("PdfLibrary", "", "PDF Library that used to generate this sample for MC reweighting (MC only)" ); @@ -50,10 +49,14 @@ int main( int argc, char* argv[] ) std::vector monitorBranches = NamedParameter("Monitors" , std::vector() ).getVector(); std::vector branchFormat = NamedParameter("BranchFormat" , std::vector() ).getVector(); std::vector friends = NamedParameter("Friends" , std::vector() ).getVector(); - bool usePIDCalib = NamedParameter("usePIDCalib" , false ); - bool rejectMultipleCandidates = NamedParameter("rejectMultipleCandidates", true ); + std::vector idBranches = NamedParameter("IdBranches" , std::vector() ).getVector(); + bool usePIDCalib = NamedParameter("usePIDCalib" , false); + bool rejectMultipleCandidates = NamedParameter("rejectMultipleCandidates", true ); std::string cuts = vectorToString( NamedParameter("Cut","").getVector() , " && "); EventType evtType( NamedParameter( "EventType" ).getVector() ); + + std::vector branches; + for( auto& particle : particles ) for(auto& bf : branchFormat) branches.push_back( mysprintf(bf, particle.c_str())); INFO( "Reading file " << inputFilename ); INFO( "Outputting file: " << outputFilename); @@ -83,12 +86,6 @@ int main( int argc, char* argv[] ) std::vector eventsToTake; - std::vector branches; - for( auto& particle : particles ) { - for(size_t i = 0 ; i < 4; ++i ) branches.push_back( mysprintf(branchFormat[i], particle.c_str())); - } - for(auto& branch : monitorBranches) branches.push_back( branch ); - if ( rejectMultipleCandidates ) { ULong64_t totCandidate; ULong64_t eventNumber; @@ -130,7 +127,13 @@ int main( int argc, char* argv[] ) } } - EventList evts( in_tree, evtType, Branches(branches), EntryList(eventsToTake), GetGenPdf(false), ApplySym(true) ); + EventList evts( in_tree, evtType, Branches(branches), + EntryList(eventsToTake), + GetGenPdf(false), + ApplySym(true) , + ExtraBranches(monitorBranches), + IdBranches(idBranches), + InputUnits(Units::MeV) ); INFO( "Branches = ["<< vectorToString(branches, ", " ) << "]" ); @@ -182,8 +185,6 @@ int main( int argc, char* argv[] ) evts[i].setWeight( weight ); } } - evts.transform( [=](auto& event){ for( size_t i = 0 ; i < 4*evtType.size(); ++i ) event[i] /= 1000. ; } ); - if ( pdfLibrary != "" ) { INFO( "Setting generator level PDF from " << pdfLibrary ); void* handle = dlopen( pdfLibrary.c_str(), RTLD_NOW ); @@ -208,9 +209,13 @@ int main( int argc, char* argv[] ) outputFile->Close(); TFile* outputPlotFile = TFile::Open( plotsName.c_str(), "RECREATE" ); auto plots = evts.makeDefaultProjections(); + auto proj = Projection([](auto& event){ return sqrt(event.s({0,1,2,3})) ; }, "m_D", "m_D",100, 1.8, 1.9 ); for ( auto& plot : plots ) { INFO( "Writing plot " << plot->GetName() << " to file" ); plot->Write(); } + proj( evts )->Write(); + for( int i = 0 ;i != 4; ++i ) + Projection([i](auto& event){ return sqrt(event.s(i)) ; }, "m_"+std::to_string(i), "m_D",100, 0, 1.0 )(evts)->Write(); outputPlotFile->Close(); } diff --git a/doc/release.notes b/doc/release.notes index 186a1246b62..6b1c47a5a5d 100644 --- a/doc/release.notes +++ b/doc/release.notes @@ -3,6 +3,11 @@ ! Responsible : Tim Evans ! Purpose : !----------------------------------------------------------------------------- +!=================== AmpGen v2r0 2020-25-04 + - Refactored caching logic away from being computations being stored with event data. + - Support for AVX2 for amplitude evaluation / integration single/double precision. + - Updated plotting for making component amplitude plots. + - Better thread safety of integration should improve fit stability. !=================== AmpGen v1r2 2019-11-12 ================== - New phase space Generator TreePhaseSpace for producing narrow resonances. - Improved handling of CP conjugated amplitudes. diff --git a/examples/FitterWithPolarisation.cpp b/examples/FitterWithPolarisation.cpp index 4e0abc26d69..79620f5d706 100644 --- a/examples/FitterWithPolarisation.cpp +++ b/examples/FitterWithPolarisation.cpp @@ -32,7 +32,7 @@ #include #include -#if ENABLE_AVX2 +#if ENABLE_AVX #include "AmpGen/EventListSIMD.h" using EventList_type = AmpGen::EventListSIMD; #else diff --git a/examples/SignalOnlyFitter.cpp b/examples/SignalOnlyFitter.cpp index ef256081c11..611ae7dd6da 100644 --- a/examples/SignalOnlyFitter.cpp +++ b/examples/SignalOnlyFitter.cpp @@ -26,7 +26,7 @@ #include #endif -#if ENABLE_AVX2 +#if ENABLE_AVX #include "AmpGen/EventListSIMD.h" using EventList_type = AmpGen::EventListSIMD; #else diff --git a/src/Array.cpp b/src/Array.cpp index 4a135861e7e..fe66b64b347 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -19,21 +19,10 @@ Array::Array( const Expression& top, std::string Array::to_string(const ASTResolver* resolver) const { auto head = m_top.to_string(resolver); - if( is(m_address) ) - return head+"["+ std::to_string(int(std::real(m_address()))) +"]"; - auto offset = m_address.to_string(resolver); - if( resolver != nullptr && resolver->enableAVX() ) - { - return " gather( &(" + head + "), " + offset + ")"; - } - auto pos = head.find_last_of("]"); - if( pos != std::string::npos ){ - auto st1 = head.substr(0,pos); - auto st2 = head.substr(pos,head.size() - pos ); - return st1 + "+int("+offset+")" + st2; - } - else return head +"[ int("+offset+")]"; + if( resolver != nullptr && resolver->enableAVX() ) return " gather( &(" + head + "), " + offset + ")"; + if( head.find("[") == std::string::npos ) return head + "[int("+offset+")]"; + else return " * ( & (" + head + ") + int("+offset+") )"; } void Array::resolve( ASTResolver& resolver ) const diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 60c7d6f0a62..e3240a318d1 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -34,8 +34,6 @@ using namespace AmpGen; CoherentSum::CoherentSum() = default; -//ENABLE_DEBUG(CoherentSum) - CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, const std::string& prefix ) : m_rules (mps) , m_evtType (type) @@ -57,12 +55,12 @@ CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, ThreadPool tp(nThreads); for(size_t i = 0; i < m_matrixElements.size(); ++i){ tp.enqueue( [i,this,&mps,&litudes]{ - auto& [p, c] = amplitudes[i]; + auto& [p, c] = amplitudes[i]; + DebugSymbols db; m_matrixElements[i] = TransitionMatrix(p, c, - CompiledExpression( - p.getExpression(), p.decayDescriptor(), - this->m_evtType.getEventFormat(), DebugSymbols(), this->m_mps ) ); + CompiledExpression( p.getExpression(m_dbThis ? &db : nullptr), p.decayDescriptor(), + this->m_evtType.getEventFormat(), db, this->m_mps ) ); CompilerWrapper().compile( m_matrixElements[i], this->m_objCache); } ); } @@ -121,13 +119,8 @@ void CoherentSum::debug( const Event& evt, const std::string& nameMustContain ) << " ] g = [ "<< me.coupling().real() << " " << me.coupling().imag() << " ] " << m_cache( evt.index(), std::distance(&m_matrixElements[0], &me ) ) << me.decayTree.CP() ); - - // if( m_dbThis ) me.amp.debug( evt.address() ); } - //else - // for ( auto& me : m_matrixElements ) - // if ( me.amp.name().find( nameMustContain ) != std::string::npos ) me.amp.debug( evt.address() ); - // if( evt.cacheSize() != 0 ) INFO( "Pdf = " << prob_unnormalised( evt ) ); + if( m_dbThis ) for ( auto& me : m_matrixElements ) me.debug( m_events->block(0) ); INFO( "A(x) = " << getVal(evt) << " without cache: " << getValNoCache(evt) ); } @@ -330,7 +323,7 @@ complex_t CoherentSum::getVal( const Event& evt ) const for (unsigned int i = 0 ; i != m_matrixElements.size(); ++i ) { value = value + m_matrixElements[i].coefficient * m_cache(evt.index() / utils::size::value, i ); } -#if ENABLE_AVX2 +#if ENABLE_AVX return value.at(evt.index() % utils::size::value ); #else return value; diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index acf12e97540..d9c10a323ff 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -13,6 +13,7 @@ #include "AmpGen/ASTResolver.h" #include "AmpGen/ProfileClock.h" #include "AmpGen/Tensor.h" +#include "AmpGen/simd/utils.h" using namespace AmpGen; CompiledExpressionBase::CompiledExpressionBase() = default; @@ -143,7 +144,7 @@ void CompiledExpressionBase::compile(const std::string& fname) void CompiledExpressionBase::addDebug( std::ostream& stream ) const { stream << "#include\n"; - stream << "extern \"C\" std::vector>> " + stream << "extern \"C\" std::vector() << " >> " << m_progName << "_DB(" << fcnSignature() << "){\n"; for ( auto& dep : m_debugSubexpressions ) { std::string rt = "auto v" + std::to_string(dep.first) + " = " + dep.second.to_string(m_resolver.get()) +";"; @@ -155,8 +156,8 @@ void CompiledExpressionBase::addDebug( std::ostream& stream ) const const auto expression = m_db[i].second; stream << std::endl << "{\"" << m_db[i].first << "\","; if ( expression.to_string(m_resolver.get()) != "NULL" ) - stream << expression.to_string(m_resolver.get()) << "}" << comma; - else stream << "-999}" << comma ; + stream << typeof() << "("<< expression.to_string(m_resolver.get()) << ")}" << comma; + else stream << typeof() << "(-999.,0.)}" << comma ; } } diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index b27e031bb34..1cc55061d28 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -53,8 +53,10 @@ void CompilerWrapper::generateSource( const CompiledExpressionBase& expression, { std::ofstream output( filename ); for ( auto& include : m_includes ) output << "#include <" << include << ">\n"; - if( expression.fcnSignature().find("AVX2d") != std::string::npos ) output << "#include \"AmpGen/simd/avx2d_types.h\"\n; using namespace AmpGen::AVX2d;\n" ; - else if( expression.fcnSignature().find("AVX2") != std::string::npos ) output << "#include \"AmpGen/simd/avx2_types.h\"\n; using namespace AmpGen::AVX2;\n;" ; + if( expression.fcnSignature().find("AVX2d") != std::string::npos ) output << "#include \"AmpGen/simd/avx2d_types.h\"\n; using namespace AmpGen::AVX2d;\n" ; + else if( expression.fcnSignature().find("AVX2") != std::string::npos ) output << "#include \"AmpGen/simd/avx2_types.h\"\n; using namespace AmpGen::AVX2;\n;" ; + else if( expression.fcnSignature().find("AVX512d") != std::string::npos ) output << "#include \"AmpGen/simd/avx512d_types.h\"\n; using namespace AmpGen::AVX512d;\n;" ; + else if( expression.fcnSignature().find("AVX512") != std::string::npos ) output << "#include \"AmpGen/simd/avx512_types.h\"\n; using namespace AmpGen::AVX512;\n;" ; output << expression << std::endl; output.close(); } @@ -141,11 +143,13 @@ void CompilerWrapper::compileSource( const std::string& fname, const std::string std::vector compile_flags = NamedParameter("CompilerWrapper::Flags", {"-Ofast", "--std="+get_cpp_version()}); - #if ENABLE_AVX2 + #if ENABLE_AVX compile_flags.push_back("-march=native"); + compile_flags.push_back( std::string("-I") + AMPGENROOT) ; + #endif + #if ENABLE_AVX2d compile_flags.push_back("-mavx2"); compile_flags.push_back("-DHAVE_AVX2_INSTRUCTIONS"); - compile_flags.push_back( std::string("-I") + AMPGENROOT) ; #endif #ifdef _OPENMP compile_flags.push_back("-fopenmp"); diff --git a/src/Event.cpp b/src/Event.cpp index 3f1bf940bd9..04043c21503 100644 --- a/src/Event.cpp +++ b/src/Event.cpp @@ -89,12 +89,8 @@ void Event::swap( const unsigned& i , const unsigned& j ) std::memmove( &m_event[4*i], &tmp,sizeof(tmp)); } -/* -void Event::setCache(const complex_t& value, const unsigned& pos){ m_cache[pos] = value; } -void Event::setCache( const std::vector& value, const unsigned& pos ) +void Event::reorder( const std::vector& addresses ) { - std::memmove( m_cache.data() + pos, value.data(), sizeof(complex_t) * value.size() ); + auto copy = m_event; + for( unsigned i = 0; i != addresses.size(); ++i ) set( addresses[i], copy.data() + 4 *i ); } - -void Event::resizeCache( const unsigned int& new_size ){ m_cache.resize(new_size); } -*/ diff --git a/src/EventList.cpp b/src/EventList.cpp index 4ab59d90009..86727861ad8 100644 --- a/src/EventList.cpp +++ b/src/EventList.cpp @@ -54,6 +54,12 @@ void EventList::loadFromFile( const std::string& fname, const ArgumentPack& args gFile = current_file; } +template key_type inv_map(const std::map& mp, const value_type& k, const default_type& df = default_type()) +{ + for( const auto& [key,val] : mp ) if( val == k ) return key; + return df; +} + void EventList::loadFromTree( TTree* tree, const ArgumentPack& args ) { ProfileClock read_time; @@ -66,32 +72,36 @@ void EventList::loadFromTree( TTree* tree, const ArgumentPack& args ) auto getGenPdf = args.getArg(false).val; auto weightBranch = args.getArg(std::string("")).val; auto branches = args.getArg().val; + auto extraBranches= args.getArg().val; auto applySym = args.getArg(false).val; auto entryList = args.getArg().val; auto eventFormat = m_eventType.getEventFormat( true ); - - Event temp( branches.size() == 0 ? eventFormat.size() : branches.size()); - + auto inputUnits = args.getArg(Units::GeV); + auto idBranches = args.getArg({}).val; + Event temp( eventFormat.size() + extraBranches.size()); temp.setWeight( 1 ); temp.setGenPdf( 1 ); tree->SetBranchStatus( "*", 0 ); - - TreeReader tr( tree ); - if( branches.size() != 0 ){ - INFO("Branches = [" << vectorToString(branches, ", ") << "]" ); - for ( auto branch = branches.begin(); branch != branches.end(); ++branch ) { - unsigned int pos = std::distance( branches.begin(), branch ); - tr.setBranch( *branch, &(temp[pos]) ); - if( pos >= eventFormat.size() ){ - INFO("Specifiying event extension: " << *branch << " " << pos << " " << eventFormat.size() ); - m_extensions[ *branch ] = pos; - } + TreeReader tr( tree ); + bool hasEnergy = branches.size() == 0 || branches.size() == 4 * m_eventType.size(); // if the energy of the particle has been explicitly specified // + if( branches.size() != 0 ) + { + DEBUG("Branches = [" << vectorToString(branches, ", ") << "]" ); + for (unsigned p = 0 ; p != branches.size(); ++p ) + { + auto pos = hasEnergy ? p : 4 * int(p/3) + p % 3 ; + DEBUG("Setting branch: " << branches[p] << " pos: " << pos << " fmt = " << inv_map( eventFormat, pos, "NOT FOUND" ) << " has energy? " << hasEnergy ); + tr.setBranch( branches[p], &(temp[pos]) ); } + auto pos = eventFormat.size(); + for( const auto& branch : extraBranches ) m_extensions[branch] = pos++; } - else { - for ( auto& branch : eventFormat ){ - tr.setBranch( branch.first, &(temp[branch.second]) ); - } + else for ( auto& branch : eventFormat ) tr.setBranch( branch.first, &(temp[branch.second]) ); + std::vector ids( m_eventType.size() ); + if( idBranches.size() != 0 ) + { + if( idBranches.size() != m_eventType.size() ){ FATAL("Number of ID branches should be number of final state particles"); } + for( int i = 0; i != ids.size(); ++i ) tr.setBranch( idBranches[i], ids.data() + i); } if( getGenPdf ) tr.setBranch( "genPdf", temp.pGenPdf() ); if( weightBranch != "" ) tr.setBranch( weightBranch, temp.pWeight() ); @@ -105,13 +115,18 @@ void EventList::loadFromTree( TTree* tree, const ArgumentPack& args ) for( int i = 0 ; i < evtList->GetN(); ++i ) entryList.push_back( evtList->GetEntry(i) ); } - bool hasEventList = entryList.size() != 0; - unsigned int nEvents = hasEventList ? entryList.size() : tree->GetEntries(); - m_data.reserve( nEvents ); + if( entryList.size() != 0 ) tr.setEntryList( entryList ); + m_data.reserve( tr.nEntries() ); auto symmetriser = m_eventType.symmetriser(); - for ( unsigned int evt = 0; evt < nEvents; ++evt ) { - tr.getEntry( hasEventList ? entryList[evt] : evt ); - if( applySym ) symmetriser( temp ); + auto automaticOrdering = m_eventType.automaticOrdering(); + for (const auto& evt : tr) { + if( inputUnits != Units::GeV ) for( unsigned k = 0; k != eventFormat.size(); ++k ) temp[k] *= to_double(inputUnits); + if( idBranches.size() != 0 ) automaticOrdering(temp, ids); + if( applySym ) symmetriser(temp); + if( ! hasEnergy ){ + for( unsigned int k = 0 ; k != m_eventType.size(); ++k ) + temp[4*k + 3] = sqrt( m_eventType.mass(k) * m_eventType.mass(k) + temp[4*k+0]*temp[4*k+0] + temp[4*k+1]*temp[4*k+1] + temp[4*k+2]*temp[4*k+2] ); + } temp.setIndex( m_data.size() ); m_data.push_back( temp ); } @@ -132,10 +147,8 @@ TTree* EventList::tree( const std::string& name, const std::vector& double genPdf = 1; double weight = 1; auto format = m_eventType.getEventFormat( true ); - for ( const auto& f : format ) outputTree->Branch( f.first.c_str(), tmp.address( f.second ) ); for ( const auto& f : m_extensions ) outputTree->Branch( f.first.c_str(), tmp.address( f.second ) ); - outputTree->Branch( "genPdf", &genPdf ); outputTree->Branch( "weight", &weight ); for ( const auto& evt : *this ) { @@ -185,12 +198,6 @@ TH2D* EventList::makeProjection( const Projection2D& projection, const ArgumentP return plot; } -// void EventList::resetCache() -// { -// m_index.clear(); -// //m_cache.clear(); -// } - double EventList::integral() const { return std::accumulate( std::begin(*this), std::end(*this), 0, [](double rv, const auto& evt){ return rv + evt.weight(); } ); @@ -211,10 +218,3 @@ void EventList::erase(const std::vector::iterator& begin, { m_data.erase( begin, end ); } - -//void EventList::reserveCache(const size_t& size) -//{ -// if ( size * m_data.size() >= m_cache.size() ) -// m_cache.reserve( m_data.size() * m_cache.size() ); -//} - diff --git a/src/EventListSIMD.cpp b/src/EventListSIMD.cpp index 3c7a644c34c..2ba7040bcb4 100644 --- a/src/EventListSIMD.cpp +++ b/src/EventListSIMD.cpp @@ -1,4 +1,4 @@ -#if ENABLE_AVX2 +#if ENABLE_AVX #include #include @@ -81,7 +81,7 @@ void EventListSIMD::loadFromTree( TTree* tree, const ArgumentPack& args ) temp.setGenPdf( 1 ); tree->SetBranchStatus( "*", 0 ); - TreeReader tr( tree ); + TreeReader tr( tree ); if( branches.size() != 0 ){ INFO("Branches = [" << vectorToString(branches, ", ") << "]" ); for ( auto branch = branches.begin(); branch != branches.end(); ++branch ) { diff --git a/src/EventType.cpp b/src/EventType.cpp index ceff945be56..9adc9b788a8 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -230,7 +230,7 @@ std::function EventType::symmetriser() const for ( auto& s : shuffle ) shuffle_string += std::to_string( s ) + " "; DEBUG( "Shuffle = " << shuffle_string ); } - auto fcn = [shuffles, rng]( auto& event ) mutable -> void { + return [shuffles, rng]( auto& event ) mutable -> void { for ( auto shuffled : shuffles ) { for ( unsigned int index = 0; index < shuffled.size(); ++index ) { unsigned int j = std::uniform_int_distribution( 0, index )( rng ); @@ -240,9 +240,44 @@ std::function EventType::symmetriser() const } } }; - return fcn; } +std::function&)> EventType::automaticOrdering() const +{ + std::vector ids; + for( unsigned i = 0 ; i != m_particleNames.size(); ++i ) ids.push_back( ParticleProperties::get(m_particleNames[i])->pdgID() ); + auto matches = [](const auto& c1, const auto& c2 , unsigned sgn = +1) + { + std::vector used( c1.size(), false ); + for(unsigned i = 0; i != c1.size(); ++i ) + { + for( unsigned j = 0; j != c2.size(); ++j ) + { + if( c1[i] == sgn * c2[j] && ! used[j] ) used[j] = true; + } + } + return std::all_of( std::begin(used), std::end(used), [](auto b) { return b; } ) ; + }; + + return [ids, matches](auto& event, const auto& actual_ids) -> void { + std::vector new_addresses( ids.size(), 999 ); + int sgn = +1; + if( matches(ids, actual_ids ) ) sgn = +1; + else if( matches(ids, actual_ids, -1 ) ) sgn = -1; + else { FATAL("Ids: " << vectorToString(actual_ids, " ") << " do not match either particle or antiparticle ["<< vectorToString(ids, " ") << "]" );} + + for( unsigned i = 0 ; i != ids.size(); ++i ) + { + for( unsigned j = 0 ; j != actual_ids.size(); ++j ) + { + if( actual_ids[j] == sgn * ids[i] && new_addresses[j]==999 ){ new_addresses[j] = i; break ; } + } + } + event.reorder( new_addresses ); + }; +} + + bool EventType::has( const std::string& name ) const { return std::any_of( m_particleNames.begin(), m_particleNames.end(), [&name](auto& it) { return it == name ; } ); diff --git a/src/Expression.cpp b/src/Expression.cpp index 9433ef4c9cf..1584bcb9621 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -15,7 +15,7 @@ #include "AmpGen/MetaUtils.h" #include "AmpGen/MsgService.h" #include "AmpGen/Types.h" - +#include "AmpGen/simd/utils.h" using namespace AmpGen; using namespace AmpGen::fcn; using namespace std::complex_literals; @@ -58,15 +58,10 @@ std::string Constant::to_string(const ASTResolver* resolver) const { }; std::string complex_type = typeof(); std::string literalSuffix = ""; - if( resolver != nullptr && resolver->enableCuda() ) - { - complex_type = "AmpGen::CUDA::complex_t"; - literalSuffix = "f"; - } - if( resolver != nullptr && resolver->enableAVX() ) - { - complex_type = "AmpGen::AVX2d::complex_t"; + if( resolver != nullptr && (resolver->enableCuda() || resolver->enableAVX()) ) + { literalSuffix = "f"; + complex_type = typeof(); } return std::imag(m_value) == 0 ? "(" + rounded_string(std::real(m_value)) +literalSuffix + ")" : complex_type +"("+rounded_string(std::real(m_value))+literalSuffix+","+rounded_string(std::imag(m_value))+literalSuffix+")"; @@ -216,7 +211,7 @@ Ternary::Ternary( const Expression& cond, const Expression& v1, const Expression } std::string Ternary::to_string(const ASTResolver* resolver) const { - return resolver != nullptr && resolver->enableAVX() ? "AmpGen::AVX2d::select(" + m_cond.to_string(resolver) + ", " + + return resolver != nullptr && resolver->enableAVX() ? "select(" + m_cond.to_string(resolver) + ", " + m_v1.to_string(resolver) + ", " + m_v2.to_string(resolver) +")" : "(" + m_cond.to_string(resolver) + "?" + m_v1.to_string(resolver) + ":" + m_v2.to_string(resolver) + ")"; } @@ -331,9 +326,8 @@ ComplexParameter::ComplexParameter( const Parameter& real, const Parameter& imag std::string ComplexParameter::to_string(const ASTResolver* resolver) const { - std::string complex_type = "std::complex"; - if( resolver != nullptr && resolver->enableCuda() ) complex_type = "AmpGen::CUDA::complex_t"; - if( resolver != nullptr && resolver->enableAVX() ) complex_type = "AmpGen::AVX2d::complex_t"; + std::string complex_type = typeof(); + if( resolver != nullptr && (resolver->enableCuda() || resolver->enableAVX()) ) complex_type = typeof(); return complex_type + "(" + m_real.to_string(resolver) + ", " + m_imag.to_string(resolver) +")"; } diff --git a/src/Integrator.cpp b/src/Integrator.cpp index 4632a44b764..70da64875db 100644 --- a/src/Integrator.cpp +++ b/src/Integrator.cpp @@ -44,7 +44,7 @@ void Integrator::integrateBlock() auto b2 = m_cache.data() + m_integrals[roll].j * m_cache.nBlocks(); for ( size_t i = 0; i < m_cache.nBlocks(); ++i ) { auto c = b1[i] * conj(b2[i]); - #if ENABLE_AVX2 + #if ENABLE_AVX re = fmadd( m_weight[i], real(c), re ); im = fmadd( m_weight[i], imag(c), im ); #else diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 86e748a55e0..bc2211757ed 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -72,7 +72,7 @@ PolarisedSum::PolarisedSum(const EventType& type, ThreadPool tp( std::thread::hardware_concurrency() ); for(unsigned i = 0; i < m_matrixElements.size(); ++i) { - // tp.enqueue( [i, &protoAmps, &polStates, this]{ + tp.enqueue( [i, &protoAmps, &polStates, this]{ Tensor thisExpression( Tensor::dim(polStates.size()) ); auto& [p, coupling] = protoAmps[i]; DebugSymbols syms; @@ -85,7 +85,7 @@ PolarisedSum::PolarisedSum(const EventType& type, p.decayDescriptor(), this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,this->m_mps ) ); CompilerWrapper().compile( m_matrixElements[i] ); - // }); + }); } } if ( stype == spaceType::flavour ) diff --git a/src/Projection.cpp b/src/Projection.cpp index 89b354a7d89..6d14b4b9a2f 100644 --- a/src/Projection.cpp +++ b/src/Projection.cpp @@ -106,7 +106,7 @@ template <> std::tuple, THStack*> Projection::projInternal(co return {hists, stack}; } -#if ENABLE_AVX2 +#if ENABLE_AVX template <> TH1D* Projection::projInternal( const EventListSIMD& events, const ArgumentPack& args) const { return events.makeProjection(*this, args); diff --git a/src/Spline.cpp b/src/Spline.cpp index 81e7de93045..c7c3de27547 100644 --- a/src/Spline.cpp +++ b/src/Spline.cpp @@ -24,20 +24,18 @@ Spline::Spline(const std::string& name, m_min(min), m_max(max) {} -Spline::Spline(const Spline& spline, - const Expression& x ) - : +Spline::Spline(const Spline& spline, const Expression& x, DebugSymbols* db ) : m_points( spline.m_points ), m_name( spline.m_name), m_nKnots( spline.m_nKnots), m_min( spline.m_min ), m_max( spline.m_max ), m_x ( x ), - m_eval( eval() ) { - } -Expression Spline::operator()( const Expression& x ) + m_eval( eval(db) ) {} + +Expression Spline::operator()( const Expression& x, DebugSymbols* db ) { - return Spline(*this,x); + return Spline(*this,x, db); } Expression AmpGen::getSpline( const std::string& name, const Expression& x, const std::string& arrayName, @@ -56,10 +54,10 @@ Expression AmpGen::getSpline( const std::string& name, const Expression& x, cons max = NamedParameter( name + "::Spline::Max", 0. ); } std::string spline_name = name + "::Spline::"+arrayName; - return Spline( spline_name, nBins, min,max )(x); + return Spline(spline_name, nBins, min, max)(x, dbexpressions); } -Expression Spline::eval() const +Expression Spline::eval(DebugSymbols* db) const { Expression x = make_cse(m_x); double spacing = ( m_max - m_min ) / ( (double)m_nKnots - 1. ); @@ -73,6 +71,13 @@ Expression Spline::eval() const + m_points[bin+m_nKnots] * dx * dx / 2. + dx * dx * dx * ( m_points[bin+1+m_nKnots] - m_points[bin+m_nKnots] ) / ( 6. * spacing ), continuedValue ); + ADD_DEBUG(x, db ); + ADD_DEBUG(dx, db ); + ADD_DEBUG(bin, db ); + ADD_DEBUG(returnValue, db ); + ADD_DEBUG( m_points[bin], db ); + for( int i = 0 ; i != m_points.size(); ++i ) + ADD_DEBUG( m_points[Constant(i) + 0.1], db ); return make_cse(returnValue); } diff --git a/src/TreeReader.cpp b/src/TreeReader.cpp new file mode 100644 index 00000000000..42ec42513ae --- /dev/null +++ b/src/TreeReader.cpp @@ -0,0 +1,34 @@ +#include "AmpGen/TreeReader.h" +using namespace AmpGen; + +TreeReader::TreeReader( TTree* tree ) : m_tree( tree ) {} + +void TreeReader::setEntryList( const std::vector& entryList ){ m_entryList = entryList ; } + +void TreeReader::unsetEntryList(){ m_entryList.clear() ; } + +void TreeReader::getEntry( const unsigned int& entry ) +{ + if(!m_ready ) prepare(); + m_tree->GetEntry( m_entryList.size() == 0 ? entry : m_entryList[entry] ); + for ( auto& branch : m_branches ) branch->transfer(); +} + +void TreeReader::prepare() +{ + for ( auto& branch : m_branches ) { + m_tree->SetBranchStatus( branch->name.c_str(), "1" ); + m_tree->SetBranchAddress( branch->name.c_str(), branch->address() ); + } + m_ready = true; +} + +size_t TreeReader::nEntries() const { return m_entryList.size() == 0 ? m_tree->GetEntries() : m_entryList.size(); } + +TreeReader::~TreeReader() +{ + for ( auto& branch : m_branches ) delete branch; +} + +TreeReader::Iterator TreeReader::begin() { getEntry(0); return Iterator( 0, this ); } +TreeReader::Iterator TreeReader::end() { return Iterator( nEntries(), this ); } diff --git a/src/Units.cpp b/src/Units.cpp new file mode 100644 index 00000000000..121791d3ddc --- /dev/null +++ b/src/Units.cpp @@ -0,0 +1,13 @@ + +#include "AmpGen/Units.h" +#include "AmpGen/Utilities.h" + +namespace AmpGen { + complete_enum(Units, TeV, GeV, MeV, KeV) +} + +double AmpGen::to_double(const AmpGen::Units& unit) +{ + static constexpr std::array value_table = {TeV, GeV, MeV, KeV}; + return value_table[unsigned(unit)]; +} diff --git a/src/Utilities.cpp b/src/Utilities.cpp index e5f135bfe39..a03553b20fc 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -281,13 +281,12 @@ void AmpGen::printSplash() #elif defined(__GNUC__) || defined(__GNUG__) std::cout << "gcc " << __GNUC__ << "." << __GNUC_MINOR__ << "." << __GNUC_PATCHLEVEL__; #endif - #if ENABLE_AVX2 - std::cout << " (avx2;"; - #if DOUBLE_PRECISION - std::cout << " double)"; - #else - std::cout << " single)"; - #endif + #if ENABLE_AVX2d + std::cout << " (avx2; double)"; + #elif ENABLE_AVX2f + std::cout << " (avx2; single)"; + #elif ENABLE_AVX512 + std::cout << " (avx512; double)"; #endif std::cout << " " << __DATE__ << " " << __TIME__ << bold_off << "\n\n"; diff --git a/test/test_avx2d.cpp b/test/test_avx2d.cpp index f914bf28790..d1ce7d48435 100644 --- a/test/test_avx2d.cpp +++ b/test/test_avx2d.cpp @@ -8,18 +8,19 @@ namespace utf = boost::unit_test; #if ENABLE_AVX2 -#include "AmpGen/simd/avx2d_types.h" +#include "AmpGen/simd/utils.h" using namespace AmpGen; +using namespace AmpGen::AVX2d; BOOST_AUTO_TEST_CASE( test_log ) { - AVX2d::float_t p(0.3, 0.5, 10.0, 7.0); + AVX2d::real_v p(0.3, 0.5, 10.0, 7.0); auto logged = AVX2d::log( p ).to_array() ; - BOOST_TEST( logged[0] == std::log(0.3), boost::test_tools::tolerance(1e-15 ) ); - BOOST_TEST( logged[1] == std::log(0.5), boost::test_tools::tolerance(1e-15 ) ); - BOOST_TEST( logged[2] == std::log(10.0), boost::test_tools::tolerance(1e-15 ) ); - BOOST_TEST( logged[3] == std::log(7.0), boost::test_tools::tolerance(1e-15 ) ); + BOOST_TEST( logged[0] == std::log(0.3), boost::test_tools::tolerance(5e-10 ) ); + BOOST_TEST( logged[1] == std::log(0.5), boost::test_tools::tolerance(5e-10 ) ); + BOOST_TEST( logged[2] == std::log(10.0), boost::test_tools::tolerance(5e-10 ) ); + BOOST_TEST( logged[3] == std::log(7.0), boost::test_tools::tolerance(5e-10 ) ); } BOOST_AUTO_TEST_CASE( test_fmod ) @@ -27,8 +28,8 @@ BOOST_AUTO_TEST_CASE( test_fmod ) std::vector a = {5.1, -5.1, 5.1, -5.1}; std::vector b = {3.0, +3.0, -3.0, -3.0}; - AVX2d::float_t av( a.data() ); - AVX2d::float_t bv( b.data() ); + AVX2d::real_v av( a.data() ); + AVX2d::real_v bv( b.data() ); auto modv = AVX2d::fmod(av,bv); BOOST_TEST_MESSAGE( "fmod = " << modv ); @@ -42,30 +43,29 @@ BOOST_AUTO_TEST_CASE( test_fmod ) BOOST_AUTO_TEST_CASE( test_double_to_int ) { - std::vector a = {17.4, -19.2, 12.1, -4007.3}; - auto f = AVX2d::double_to_int( AVX2d::float_t( a.data() )); - alignas(32) uint64_t t[4]; + std::vector a = {17.4, 19.2, 12.1, 4007.3}; + auto f = udouble_to_uint( real_v( a.data() )); + alignas(32) uint64_t t[ utils::size::value ]; _mm256_store_si256( (__m256i*)t, f); BOOST_TEST( t[0] == 17 ); - BOOST_TEST( t[1] == -19 ); + BOOST_TEST( t[1] == 19 ); BOOST_TEST( t[2] == 12 ); - BOOST_TEST( t[3] == -4007 ); + BOOST_TEST( t[3] == 4007 ); } BOOST_AUTO_TEST_CASE( test_gather ) { // 0 1 2 3 4 5 6 std::vector data = { 15.4, 19.7, 121.8, -15.6, M_PI, sqrt(2), 5.7, 12 }; - std::vector addr = { 0, 5, 3, 3 }; - auto v = AVX2d::gather( data.data(), AVX2d::float_t(addr.data()) ).to_array(); + std::vector addr = { 0.2, 5.3, 3.1, 4.1 }; + auto v = AVX2d::gather( data.data(), AVX2d::real_v(addr.data()) ).to_array(); BOOST_TEST( v[0] == data[0] ); BOOST_TEST( v[1] == data[5] ); BOOST_TEST( v[2] == data[3] ); - BOOST_TEST( v[3] == data[3] ); + BOOST_TEST( v[3] == data[4] ); } - #else BOOST_AUTO_TEST_CASE( test_dummy ) { From e8180a048f9a6059bc3017db74a329135de0f856 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 28 Apr 2020 14:04:35 +0200 Subject: [PATCH 196/250] fix avx512d types, units for OSX --- AmpGen/Units.h | 15 ++++----------- AmpGen/simd/avx512d_types.h | 1 + src/Units.cpp | 4 ++-- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/AmpGen/Units.h b/AmpGen/Units.h index 9e376d122d7..c7e88da4570 100644 --- a/AmpGen/Units.h +++ b/AmpGen/Units.h @@ -3,21 +3,14 @@ #include "AmpGen/enum.h" namespace AmpGen { -/* - struct NewUnits { - static unsigned TeV = 0; - static unsigned GeV = 1; - static unsigned MeV = 2; - static unsigned KeV = 3; - - }; -*/ + static const double TeV = 1000; static const double GeV = 1; static const double MeV = 0.001; static const double KeV = 0.001*0.001; - - declare_enum( Units, TeV, GeV, MeV, KeV ) + static const double eV = 0.001*0.001*0.001; + + declare_enum( Units, TeV, GeV, MeV, KeV, eV ) double to_double(const Units& unit ); } #endif diff --git a/AmpGen/simd/avx512d_types.h b/AmpGen/simd/avx512d_types.h index a43af591688..36d9695af77 100644 --- a/AmpGen/simd/avx512d_types.h +++ b/AmpGen/simd/avx512d_types.h @@ -132,6 +132,7 @@ namespace AmpGen { struct complex_v { real_v re; real_v im; + static constexpr unsigned size = 8; typedef std::complex scalar_type; real_v real() const { return re; } diff --git a/src/Units.cpp b/src/Units.cpp index 121791d3ddc..ff8909af72c 100644 --- a/src/Units.cpp +++ b/src/Units.cpp @@ -3,11 +3,11 @@ #include "AmpGen/Utilities.h" namespace AmpGen { - complete_enum(Units, TeV, GeV, MeV, KeV) + complete_enum(Units, TeV, GeV, MeV, KeV, eV) } double AmpGen::to_double(const AmpGen::Units& unit) { - static constexpr std::array value_table = {TeV, GeV, MeV, KeV}; + static constexpr double value_table[5] = {TeV, GeV, MeV, KeV, eV}; return value_table[unsigned(unit)]; } From c0c7f1cd3f0448729577b365ae305d2092f0ed13 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 28 Apr 2020 14:17:21 +0200 Subject: [PATCH 197/250] fix units for osx --- src/Units.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Units.cpp b/src/Units.cpp index ff8909af72c..9ae73ad916d 100644 --- a/src/Units.cpp +++ b/src/Units.cpp @@ -8,6 +8,6 @@ namespace AmpGen { double AmpGen::to_double(const AmpGen::Units& unit) { - static constexpr double value_table[5] = {TeV, GeV, MeV, KeV, eV}; + static const double value_table[5] = {TeV, GeV, MeV, KeV, eV}; return value_table[unsigned(unit)]; } From 867cf2a9a7132c9bcec622524ce453124ece0b9e Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sat, 16 May 2020 14:19:40 +0200 Subject: [PATCH 198/250] Progress towards SIMD compatible generation, various fixes --- AmpGen/ASTResolver.h | 4 +- AmpGen/AmplitudeRules.h | 6 +- AmpGen/CacheTransfer.h | 10 +- AmpGen/CoherentSum.h | 10 +- AmpGen/CompiledExpression.h | 21 ++-- AmpGen/EventList.h | 13 +- AmpGen/EventListSIMD.h | 13 ++ AmpGen/EventType.h | 6 +- AmpGen/ExpressionParser.h | 1 + AmpGen/Factory.h | 2 +- AmpGen/Generator.h | 219 ++++++++++++++++----------------- AmpGen/MetaUtils.h | 18 ++- AmpGen/Minimiser.h | 22 +--- AmpGen/NamedParameter.h | 2 +- AmpGen/PolarisedSum.h | 3 +- AmpGen/ProfileClock.h | 11 +- AmpGen/Projection.h | 7 +- AmpGen/Spline.h | 2 +- AmpGen/Store.h | 43 ++++--- AmpGen/SumPDF.h | 2 +- AmpGen/TreePhaseSpace.h | 23 ++-- AmpGen/TreeReader.h | 3 +- AmpGen/Units.h | 11 +- AmpGen/Utilities.h | 2 +- AmpGen/simd/avx2d_types.h | 82 +++++------- AmpGen/simd/utils.h | 14 ++- CMakeLists.txt | 4 +- Standalone.cmake | 20 +-- apps/DataConverter.cpp | 14 +-- apps/Fitter.cpp | 2 +- apps/Generator.cpp | 142 +++++++++++++-------- examples/QcGenerator.cpp | 2 +- src/ASTResolver.cpp | 3 +- src/CacheTransfer.cpp | 14 +-- src/CoherentSum.cpp | 9 +- src/CompiledExpressionBase.cpp | 6 +- src/EventList.cpp | 48 ++++++-- src/EventListSIMD.cpp | 15 +-- src/EventType.cpp | 19 +-- src/Expression.cpp | 8 +- src/ExpressionParser.cpp | 14 ++- src/Kinematics.cpp | 4 +- src/Lineshapes/BW.cpp | 6 +- src/PhaseSpace.cpp | 27 ++-- src/PolarisedSum.cpp | 24 +++- src/Projection.cpp | 20 ++- src/Spline.cpp | 6 +- src/TreePhaseSpace.cpp | 130 +++++++++---------- src/Units.cpp | 4 +- test/test_avx2d.cpp | 33 ++++- 50 files changed, 638 insertions(+), 486 deletions(-) diff --git a/AmpGen/ASTResolver.h b/AmpGen/ASTResolver.h index aa978026649..bbad189fb1c 100644 --- a/AmpGen/ASTResolver.h +++ b/AmpGen/ASTResolver.h @@ -36,7 +36,7 @@ namespace AmpGen { { auto it = m_cacheFunctions.find(name); if( it != m_cacheFunctions.end() ) return it->second->address(); - auto cacheFunction = std::make_shared(m_nParameters, args... ); + auto cacheFunction = std::make_shared(m_nParameters, name, args... ); m_cacheFunctions[name] = cacheFunction; m_nParameters += cacheFunction->size(); return m_nParameters - cacheFunction->size(); @@ -63,8 +63,8 @@ namespace AmpGen { std::map m_tempTrees; /// temporary store of sub-trees for performing cse reduction unsigned int m_nParameters; /// Number of parameters bool m_enable_cuda {false}; /// flag to generate CUDA code <> - bool m_enable_avx {false};/// flag to generate vectorised code <> bool m_enable_compileTimeConstants {false}; /// flag to enable compile time constants <> + bool m_enable_avx {false}; /// flag to generate code using AVX instructions <> }; template <> void ASTResolver::resolve( const Parameter& obj ); diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index f7d0be128a2..ed44420896f 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -177,7 +177,7 @@ namespace AmpGen const std::vector operator()(const Event& event) const { - std::vector rt(4); + std::vector rt(size); #if ENABLE_AVX amp_type::operator()(rt.data(), 1, externBuffer().data(), EventListSIMD::makeEvent(event).data()); #else @@ -186,7 +186,9 @@ namespace AmpGen return rt; } template auto operator()(arg_types... args ) const { return amp_type::operator()(args...) ; } - + #if ENABLE_AVX + void debug( const Event& event ) const { amp_type::debug(EventListSIMD::makeEvent(event).data() ) ; } + #endif const std::string decayDescriptor() const { return decayTree.decayDescriptor() ; } Particle decayTree; diff --git a/AmpGen/CacheTransfer.h b/AmpGen/CacheTransfer.h index 6a4e162adc8..4a2748e60dc 100644 --- a/AmpGen/CacheTransfer.h +++ b/AmpGen/CacheTransfer.h @@ -3,6 +3,7 @@ #include #include +#include namespace AmpGen { @@ -13,7 +14,7 @@ namespace AmpGen { public: CacheTransfer(); - CacheTransfer( const size_t& address, const double& value=0, const size_t& size=1); + CacheTransfer( const size_t& address, const std::string& name, const double& value=0, const size_t& size=1); virtual ~CacheTransfer() = default; size_t address() const { return m_address ; } @@ -25,13 +26,14 @@ namespace AmpGen protected: size_t m_address = {0}; size_t m_size = {0}; - double m_value = {0}; + double m_value = {0}; + std::string m_name = {""}; }; class ParameterTransfer : public CacheTransfer { public: - ParameterTransfer( const size_t& address, AmpGen::MinuitParameter* source ); + ParameterTransfer( const size_t& address, const std::string& name, AmpGen::MinuitParameter* source ); virtual ~ParameterTransfer() = default; size_t size() const override { return 1 ; } @@ -40,7 +42,7 @@ namespace AmpGen void print() const override; protected: - AmpGen::MinuitParameter* m_source = {nullptr}; + MinuitParameter* m_source = {nullptr}; }; } // namespace AmpGen diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index c50404fa02e..9b0bf903f7c 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -77,9 +77,15 @@ namespace AmpGen void setEvents( const EventList_type& list ); void setMC( const EventList_type& sim ); #if ENABLE_AVX - void setEvents( const EventList& list) { m_ownEvents = true; setEvents( *(new EventListSIMD(list)) ) ; } - void setMC( const EventList& list) { setMC( *(new EventListSIMD(list)) ) ; } + void setEvents( const EventList& list) { + WARNING("Setting events from a AoS container, will need to make a copy"); + m_ownEvents = true; setEvents( *(new EventListSIMD(list)) ) ; } + void setMC ( const EventList& list) { + WARNING("Setting integration events from a AoS container, will need to make a copy"); + setMC( *(new EventListSIMD(list)) ) ; } + double operator()(const double*, const unsigned) const; #endif + float_v operator()(const float_v*, const unsigned) const; real_t operator()(const Event& evt ) const { return m_weight*std::norm(getVal(evt))/m_norm; } diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index eaf86b1c5d2..6b3812564b6 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -22,10 +22,8 @@ namespace AmpGen but in principal support also exists for computing coupled channel propagators (i.e. returning array types) */ namespace detail { - template struct size_of { unsigned operator()(){ return sizeof(T); } }; - template <> struct size_of { unsigned operator()(){ - WARNING("Asking for the size_of the return buffer of an RTO expression"); - return 0; } }; + template struct size_of { static constexpr unsigned value = sizeof(T); }; + template <> struct size_of { static constexpr unsigned value = 0; } ; } template class CompiledExpression; @@ -56,7 +54,7 @@ namespace AmpGen CompiledExpression( const std::string& name = "" ) : CompiledExpressionBase( name ) {}; std::vector externBuffer() const { return m_externals ; } - std::string returnTypename() const override { return typeof(); } + std::string returnTypename() const override { return type_string(); } std::string fcnSignature() const override { return CompiledExpressionBase::fcnSignature(typelist(), use_rto()); @@ -90,7 +88,12 @@ namespace AmpGen INFO( "Hash = " << hash() ); INFO( "IsReady? = " << isReady() << " IsLinked? " << (m_fcn.isLinked() ) ); INFO( "args = ["<< vectorToString( m_externals, ", ") <<"]"); - for( auto& c : m_cacheTransfers ){ c->print() ; } + std::vector ordered_cache_functors; + for( const auto& c : m_cacheTransfers ) ordered_cache_functors.push_back( c.get() ); + std::sort( ordered_cache_functors.begin(), + ordered_cache_functors.end(), + [](auto& c1, auto& c2 ) { return c1->address() < c2->address() ; } ); + for( auto& c : ordered_cache_functors ) c->print() ; } void setExternal( const double& value, const unsigned int& address ) override @@ -128,7 +131,7 @@ namespace AmpGen stream << " const size_t& N, " << " const size_t& eventSize, " << " const size_t& cacheSize, "; - stream << typeof() << " * rt, "; + stream << type_string() << " * rt, "; stream << CompiledExpressionBase::fcnSignature(typelist(), use_rto(), false) << ") {\n"; stream << "#pragma omp parallel for\n"; stream << "for( size_t i = 0; i < N/" << utils::size::value << "; ++i ){\n"; @@ -149,7 +152,7 @@ namespace AmpGen bool isReady() const override { return m_fcn.isLinked(); } bool isLinked() const { return m_fcn.isLinked() ; } - unsigned returnTypeSize() const override { return detail::size_of()(); } + unsigned returnTypeSize() const override { return detail::size_of::value; } template < class T > RETURN_TYPE operator()( const T* event ) const @@ -173,7 +176,7 @@ namespace AmpGen FATAL( "Function" << name() << " debugging symbols not linked" ); } std::vector> debug_results; - if constexpr(std::is_same::value) debug_results = m_fdb( nullptr, &( m_externals[0] ), event ); + if constexpr(std::is_same::value) debug_results = m_fdb( nullptr, 0, &( m_externals[0] ), event ); else debug_results = m_fdb( &(m_externals[0]), event); for( auto& debug_result : debug_results ){ auto val = debug_result.second; diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index aadd68eea37..8d3f742cf6c 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -75,15 +75,20 @@ namespace AmpGen const double* block(const unsigned pos) const { return m_data[pos].address(); } real_t weight( const size_t& pos) const { return m_data[pos].weight(); } real_t genPDF( const size_t& pos) const { return m_data[pos].genPdf(); } - void reserve( const size_t& size ) { m_data.reserve( size ); } - void resize ( const size_t& size ) { m_data.resize(size) ; } - void push_back( const Event& evt ) { m_data.push_back( evt ); } - void emplace_back( const Event& evt) { m_data.emplace_back(evt) ; } + void reserve( const size_t& size ); + void resize ( const size_t& size ); + void push_back( const Event& evt ); + void emplace_back( const Event& evt); void setEventType( const EventType& type ) { m_eventType = type; } void add( const EventList& evts ); void loadFromTree( TTree* tree, const ArgumentPack& args ); void loadFromFile( const std::string& fname, const ArgumentPack& args ); void clear(); + void setWeight( const unsigned int& pos, const double& w, const double&g=+1) + { + m_data[pos].setWeight(w); + m_data[pos].setGenPdf(g); + } void erase( const std::vector::iterator& begin, const std::vector::iterator& end ); TTree* tree( const std::string& name, const std::vector& extraBranches = {} ) const; diff --git a/AmpGen/EventListSIMD.h b/AmpGen/EventListSIMD.h index 248deff8455..9c7900dd507 100644 --- a/AmpGen/EventListSIMD.h +++ b/AmpGen/EventListSIMD.h @@ -63,8 +63,21 @@ namespace AmpGen const auto& store() const { return m_data; } const Event at(const unsigned& p) const { return EventListSIMD::operator[](p) ; } const float_v* block(const unsigned& p) const { return m_data.data() + p * m_data.nFields(); } + float_v* block(const unsigned& p) { return m_data.data() + p * m_data.nFields(); } float_v weight(const unsigned& p) const { return m_weights[p]; } float_v genPDF(const unsigned& p) const { return m_genPDF[p]; } + + void setWeight( const unsigned& block, const float_v& w, const float_v& g=1) + { + m_weights[block] = w; + m_genPDF[block] = g; + } + void resize( const unsigned nEvents ) + { + m_data = Store( nEvents, m_eventType.eventSize() ); + m_weights.resize( aligned_size(), 1); + m_genPDF.resize( aligned_size(), 1 ); + } const Event operator[]( const size_t&) const; std::array::value> scatter(unsigned) const; void gather(const std::array::value>&, unsigned); diff --git a/AmpGen/EventType.h b/AmpGen/EventType.h index d2777c0143a..191cf35f976 100644 --- a/AmpGen/EventType.h +++ b/AmpGen/EventType.h @@ -38,7 +38,7 @@ namespace AmpGen /// Counts the number of particles in this event type with /// the same name as the index'th name. std::pair count(const unsigned& index) const; - std::pair minmax( const std::vector& indices, bool isGeV = false ) const; + std::pair minmax( const std::vector& indices) const; std::vector masses() const; std::string mother() const; double mass( const unsigned& index ) const; @@ -52,7 +52,7 @@ namespace AmpGen std::string decayDescriptor() const; std::string label( const unsigned& index, bool isRoot = true ) const; std::string label( const std::vector& index, bool isRoot = true ) const; - std::vector defaultProjections(const unsigned& nBins) const; + std::vector defaultProjections(const unsigned& nBins=100) const; Projection projection(const unsigned& nBins, const std::vector& indices, const std::string& observable = "mass2") const; bool operator==( const EventType& other ) const; @@ -62,7 +62,7 @@ namespace AmpGen /// Functor to randomly symmetrise data of this event type, using the Fisher-Yates shuffle. std::function symmetriser() const; - std::function& ids)> automaticOrdering() const; + std::function& ids)> automaticOrdering() const; /// Calculates the number of spin indices associated with the initial and final state, i.e. the rank of the relevant transition matrix. std::pair dim() const; diff --git a/AmpGen/ExpressionParser.h b/AmpGen/ExpressionParser.h index 0c69776b8b0..6becfbf086d 100644 --- a/AmpGen/ExpressionParser.h +++ b/AmpGen/ExpressionParser.h @@ -1,4 +1,5 @@ #ifndef AMPGEN_EXPRESSIONPARSER_H +#define AMPGEN_EXPRESSIONPARSER_H 1 #include #include diff --git a/AmpGen/Factory.h b/AmpGen/Factory.h index 0a76926c6e4..3323914be87 100644 --- a/AmpGen/Factory.h +++ b/AmpGen/Factory.h @@ -34,7 +34,7 @@ namespace AmpGen auto ptrToStatic = getMe(); auto raw_base = ptrToStatic->m_terms.find( type ); if ( raw_base == ptrToStatic->m_terms.end() ) { - if ( !quiet ) ERROR( type << " not found in Factory<" << typeof() << typeof() << " >" ); + if ( !quiet ) ERROR( type << " not found in Factory<" << type_string() << type_string() << " >" ); return nullptr; } auto objectToReturn = raw_base->second->create(); diff --git a/AmpGen/Generator.h b/AmpGen/Generator.h index 670c6838850..4ab6e0676a1 100644 --- a/AmpGen/Generator.h +++ b/AmpGen/Generator.h @@ -7,145 +7,136 @@ #include "AmpGen/Utilities.h" #include "AmpGen/ProfileClock.h" #include "AmpGen/ProgressBar.h" +#include "AmpGen/NamedParameter.h" +#include "AmpGen/MetaUtils.h" + namespace AmpGen { - template + template class Generator { private: - EventType m_eventType; - PHASESPACE m_gps; - size_t m_generatorBlock = {5000000}; - TRandom* m_rnd = {gRandom}; - bool m_normalise = {true}; + EventType m_eventType; + phaseSpace_t m_gps; + size_t m_generatorBlock = {5000000}; + TRandom* m_rnd = {gRandom}; + bool m_normalise = {true}; public: - template - explicit Generator( const ARGS&... args ) - : m_gps(args...) - { - m_eventType = m_gps.eventType(); - setRandom( m_rnd ); - } - PHASESPACE phsp() { return m_gps; } + template explicit Generator( const ARGS&... args ) : m_gps(args...) + { + m_eventType = m_gps.eventType(); + setRandom( m_rnd ); + DEBUG("Creating generator, using: " << type_string() << " and internal store type: " << type_string() ); + } + + phaseSpace_t phsp() { return m_gps; } + void setRandom( TRandom* rand ) { m_rnd = rand; m_gps.setRandom( m_rnd ); } void setBlockSize( const size_t& blockSize ) { m_generatorBlock = blockSize; } - void setNormFlag( const bool& normSetting ) { m_normalise = normSetting; } + void setNormFlag( const bool& normSetting ) { m_normalise = normSetting; } - template void fillEventListPhaseSpace( EventList& list, const size_t& N, cut_type cut = nullptr) + template void fillEventListPhaseSpace( eventListInternal_t& events, const size_t& N, [[maybe_unused]] cut_t cut = nullptr) { - if constexpr( std::is_same::value ) + events.resize(N); + auto it = events.begin(); + while( it != events.end() ) { - if( cut != nullptr ) FATAL("This shouldn't happen..."); - list.resize(N); -// #pragma omp parallel for - for( unsigned int i = 0 ; i != N; ++i ) - { - list[i] = m_gps.makeEvent(); - list[i].setWeight( 1 ); - list[i].setIndex(i); - } - } - else { - list.reserve( N ); - while( list.size() < N ){ - Event newEvent = m_gps.makeEvent(); - newEvent.setWeight( 1 ); - if ( cut( newEvent ) ){ - newEvent.setIndex( list.size() ); - list.push_back( newEvent ); - } + *it = m_gps.makeEvent(); + if constexpr( ! std::is_same::value ) + { + if( ! cut(*it ) ) continue; } + if constexpr( std::is_same::value ) it->setIndex( it - events.begin() ); + ++it; } } - - template void fillEventList( PDF& pdf, EventList& list, const size_t& N ) + template void fillEventList( pdf_t& pdf, eventList_t& list, const size_t& N ) { fillEventList( pdf, list, N, nullptr); } - - template - void fillEventList( PDF& pdf, EventList& list, const size_t& N, HARD_CUT cut ) + template double getMax(const pdf_t& pdf, const eventListInternal_t& events) const + { + auto max = 0.; + for ( const auto& evt : events ) { - if ( m_rnd == nullptr ) { - ERROR( "Random generator not set!" ); - return; - } - double maxProb = m_normalise ? 0 : 1; - auto size0 = list.size(); - auto tStartTotal = std::chrono::high_resolution_clock::now(); - pdf.reset( true ); - ProgressBar pb(60, detail::trimmedString(__PRETTY_FUNCTION__) ); - ProfileClock t_phsp, t_eval, t_acceptReject, t_gather; - std::vector efficiencyReport(m_generatorBlock,false); - - while ( list.size() - size0 < N ) { - EventList mc( m_eventType ); - t_phsp.start(); - fillEventListPhaseSpace(mc, m_generatorBlock, cut); - t_phsp.stop(); - t_gather.start(); - pdf.setEvents( mc ); - t_gather.stop(); - t_eval.start(); - pdf.prepare(); - t_eval.stop(); - if ( maxProb == 0 ) { - double max = 0; - for ( auto& evt : mc ) { - double value = pdf(evt) / evt.genPdf(); - if ( value > max ) max = value; - } - maxProb = max * 1.5; - INFO( "Setting normalisation constant = " << maxProb ); - } - auto previousSize = list.size(); - t_acceptReject.start(); - #ifdef _OPENMP - #pragma omp parallel for - #endif - for ( size_t i=0; i < mc.size(); ++i ) - mc[i].setGenPdf(pdf(mc[i]) / mc[i].genPdf()); + auto value = pdf(evt) / evt.genPdf(); + if ( value > max ) max = value; + } + DEBUG( "Returning normalisation constant = " << max * 1.5 ); + return max; + } - for( size_t i=0; i != mc.size(); ++i ) - { - auto& evt = mc[i]; - if ( evt.genPdf() > maxProb ) { - std::cout << std::endl; - WARNING( "PDF value exceeds norm value: " << evt.genPdf() << " > " << maxProb ); - } - if ( evt.genPdf() > maxProb * m_rnd->Rndm() ){ - list.push_back(evt); - efficiencyReport[i] = true; - } - else efficiencyReport[i] = false; - if ( list.size() - size0 == N ) break; + template void fillEventList( pdf_t& pdf, eventList_t& list, const size_t& N, cut_t cut ) + { + if ( m_rnd == nullptr ) + { + ERROR( "Random generator not set!" ); + return; + } + double maxProb = m_normalise ? 0 : 1; + auto size0 = list.size(); + double totalGenerated = 0; + pdf.reset( true ); + ProgressBar pb(60, detail::trimmedString(__PRETTY_FUNCTION__) ); + ProfileClock t_phsp, t_eval, t_acceptReject, t_total; + std::vector efficiencyReport(m_generatorBlock,false); + bool accept_all = NamedParameter("AcceptAll",false); + eventListInternal_t mc( m_eventType ); + while ( list.size() - size0 < N ) { + t_phsp.start(); + fillEventListPhaseSpace(mc, m_generatorBlock, cut); + t_phsp.stop(); + t_eval.start(); + pdf.setEvents( mc ); + pdf.prepare(); + maxProb = maxProb == 0 ? 1.5 * getMax(pdf, mc) : maxProb; + auto previousSize = list.size(); + #ifdef _OPENMP + #pragma omp parallel for + #endif + for ( size_t block=0; block != mc.nBlocks(); ++block ) + mc.setWeight(block, 1.0, pdf(mc.block(block), block) / mc.genPDF(block)); + t_eval.stop(); + t_acceptReject.start(); + totalGenerated += mc.size(); + for(const auto& event : mc) + { + if ( event.genPdf() > maxProb ) { + std::cout << std::endl; + WARNING( "PDF value exceeds norm value: " << event.genPdf() << " > " << maxProb ); } - m_gps.provideEfficiencyReport( efficiencyReport ); - t_acceptReject.stop(); - double time = std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); - double efficiency = 100. * ( list.size() - previousSize ) / (double)m_generatorBlock; - pb.print( double(list.size()) / double(N), " ε[gen] = " + mysprintf("%.4f",efficiency) + "% , " + std::to_string(int(time/1000.)) + " seconds" ); - if ( list.size() == previousSize ) { - ERROR( "No events generated, PDF: " << typeof() << " is likely to be malformed" ); - break; + if ( accept_all || event.genPdf() > maxProb * m_rnd->Rndm() ){ + list.push_back(event); + efficiencyReport[event.index()] = true; } -// maxProb = 0; - } - pb.finish(); - double time = std::chrono::duration( std::chrono::high_resolution_clock::now() - tStartTotal ).count(); - INFO("Generated " << N << " events in " << time << " ms"); - INFO("Generating phase space : " << t_phsp << " ms"); - INFO("Evaluating PDF : " << t_eval << " ms"); - INFO("Doing accept/reject : " << t_acceptReject << " ms"); - INFO("Gathering : " << t_gather << " ms"); - } - template ::value>::type> - EventList generate(PDF& pdf, const size_t& nEvents ) + else efficiencyReport[event.index()] = false; + if ( list.size() - size0 == N ) break; + } + t_acceptReject.stop(); + + // m_gps.provideEfficiencyReport( efficiencyReport ); + double efficiency = 100. * ( list.size() - previousSize ) / (double)m_generatorBlock; + pb.print( double(list.size()) / double(N), " ε[gen] = " + mysprintf("%.4f",efficiency) + "% , " + std::to_string(int(t_total.count()/1000.)) + " seconds" ); + if ( list.size() == previousSize ) { + ERROR( "No events generated, PDF: " << type_string() << " is likely to be malformed" ); + break; + } + } + pb.finish(); + t_total.stop(); + INFO("Generated " << N << " events in " << t_total << " ms"); + INFO("Generating phase space : " << t_phsp << " ms"); + INFO("Evaluating PDF : " << t_eval << " ms"); + INFO("Accept/reject : " << t_acceptReject << " ms"); + INFO("Efficiency = " << double(N) * 100. / totalGenerated << " %"); + } + template ::value>::type> + EventList generate(pdf_t& pdf, const size_t& nEvents ) { EventList evts( m_eventType ); fillEventList( pdf, evts, nEvents ); @@ -178,7 +169,7 @@ namespace AmpGen /** @function PyGenerate Wrapper around the a phase space generator from a stringy event type to be used with python / numpy. - */ + */ extern "C" void PyGenerate( const char* eventType, double* out, const unsigned int size ); } // namespace AmpGen #endif diff --git a/AmpGen/MetaUtils.h b/AmpGen/MetaUtils.h index 11b33f7ca4f..3c985be4daa 100644 --- a/AmpGen/MetaUtils.h +++ b/AmpGen/MetaUtils.h @@ -15,7 +15,7 @@ namespace AmpGen and identifying if a class can be constructed in different ways. */ - template std::string typeof() + template std::string type_string() { int status = 0; std::string name = abi::__cxa_demangle( typeid( TYPE ).name(), nullptr, nullptr, &status ); @@ -25,7 +25,7 @@ namespace AmpGen return name; } - template std::string typeof( const TYPE& t ) { return typeof(); } + template std::string type_string( const TYPE& t ) { return type_string(); } namespace detail { template struct zeroType { typedef T type; }; @@ -94,8 +94,8 @@ namespace AmpGen template std::vector typelist() { std::vector< std::string > rt; - if( typeof() != "void" ) { - rt.emplace_back( typeof() ); + if( type_string() != "void" ) { + rt.emplace_back( type_string() ); auto rtp = typelist(); std::copy( rtp.begin(), rtp.end(), std::back_inserter(rt) ); } @@ -106,6 +106,16 @@ namespace AmpGen template struct isTuple>: std::true_type {}; template struct isVector : std::false_type {}; template struct isVector> : std::true_type {}; + + + #define def_has_function(function_name) \ + template \ + struct has_##function_name { \ + template static auto test(int) -> decltype(std::declval().function_name() == 1, std::true_type()); \ + template static std::false_type test(...); \ + static constexpr bool value = std::is_same(0)), std::true_type>::value; \ + } + } // namespace AmpGen #endif diff --git a/AmpGen/Minimiser.h b/AmpGen/Minimiser.h index c32c45921b9..736380d6588 100644 --- a/AmpGen/Minimiser.h +++ b/AmpGen/Minimiser.h @@ -9,6 +9,7 @@ #include #include "TMatrixTSym.h" +#include "AmpGen/MetaUtils.h" /** @cond PRIVATE */ namespace ROOT @@ -31,24 +32,13 @@ namespace AmpGen class Minimiser { private: - template - struct HasGetVal - { - typedef char YesType[1]; - typedef char NoType[2]; - template static YesType& test( decltype(&C::getVal) ) ; - template static NoType& test(...); - enum { value = sizeof(test(0)) == sizeof(YesType) }; - }; - + def_has_function(getVal); + public: - template typename std::enable_if_t::value, void> setFunction( TYPE& fcn ) - { - m_theFunction = [&fcn]() { return fcn.getVal(); }; - } - template typename std::enable_if_t::value, void> setFunction(TYPE& fcn) + template void setFunction( TYPE& fcn ) { - m_theFunction = [&fcn](){ return fcn() ; } ; + if constexpr( has_getVal::value ) m_theFunction = [&fcn]() { return fcn.getVal(); }; + else m_theFunction = fcn; } template diff --git a/AmpGen/NamedParameter.h b/AmpGen/NamedParameter.h index 461b33c4bd3..40774b215fb 100644 --- a/AmpGen/NamedParameter.h +++ b/AmpGen/NamedParameter.h @@ -76,7 +76,7 @@ namespace AmpGen } // ~NamedParameter(){ INFO("Deconstructing: " << m_name ); } void help(const T& def){ - std::string type = typeof(); + std::string type = type_string(); if( type == "std::__cxx11::basic_string, std::allocator >" ) type = "string"; std::cout << " " << bold_on << std::left << std::setw(27) << m_name << bold_off << std::setw(20) << "[" + type + "]" ; diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index a2d0a555e52..987a090dd6d 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -50,8 +50,9 @@ namespace AmpGen #if ENABLE_AVX void setEvents(EventList& evts){ m_ownEvents = true; setEvents( *new EventList_type(evts)) ; }; void setMC(EventList& evts){ setMC( *new EventList_type(evts)) ; }; + double operator()(const double*, const unsigned) const; #endif - float_v operator()( const float_v*, const unsigned) const; + float_v operator()(const float_v*, const unsigned) const; real_t operator()(const Event& evt) const; void reset(const bool& = false); void debug(const Event&); diff --git a/AmpGen/ProfileClock.h b/AmpGen/ProfileClock.h index 6da6bccbaa9..8810c325663 100644 --- a/AmpGen/ProfileClock.h +++ b/AmpGen/ProfileClock.h @@ -17,6 +17,11 @@ namespace AmpGen{ t_end = std::chrono::high_resolution_clock::now() ; t_duration += std::chrono::duration( t_end - t_start ).count(); } + double count() const + { + auto now = std::chrono::high_resolution_clock::now() ; + return std::chrono::duration(now - t_start ).count(); + } void start(){ t_start = std::chrono::high_resolution_clock::now() ; } operator double() const { return t_duration; } ; }; @@ -26,7 +31,7 @@ namespace AmpGen{ ProfileClock t; for( size_t i = 0 ; i < N; ++i ) fcn(); t.stop(); - INFO( (name == "" ? typeof() : name ) << " " << t/double(N) << "[ms] per iteration" ); + INFO( (name == "" ? type_string() : name ) << " " << t/double(N) << "[ms] per iteration" ); return t; } template @@ -46,7 +51,7 @@ namespace AmpGen{ } t /= double(N); t2 = std::sqrt( t2 / double(N) - t*t); - INFO( (name == "" ? typeof() : name ) << " " << t << " ± " << t2 << "[ms] per iteration << [" << tmin << ", " << tmax << "]" ); + INFO( (name == "" ? type_string() : name ) << " " << t << " ± " << t2 << "[ms] per iteration << [" << tmin << ", " << tmax << "]" ); return t; } @@ -56,7 +61,7 @@ namespace AmpGen{ auto z = 0 ; for( size_t i = 0 ; i < N; ++i ) z += fcn(); t.stop(); - INFO( typeof() << " " << t/double(N) << "[ms] per iteration; " << z ); + INFO( type_string() << " " << t/double(N) << "[ms] per iteration; " << z ); return t; } } diff --git a/AmpGen/Projection.h b/AmpGen/Projection.h index d1866b373c7..ce6c926ea53 100644 --- a/AmpGen/Projection.h +++ b/AmpGen/Projection.h @@ -48,7 +48,12 @@ namespace AmpGen TH1D* plot(const std::string& prefix="") const; std::function binFunctor() const; - void setRange( const double& min, const double& max ){ m_min = (min); m_max = (max) ; } + void setRange( const double& min, const double& max ) + { + m_min = min; + m_max = max; + m_width = (m_max-m_min)/double(m_nBins); + } friend class Projection2D; private: diff --git a/AmpGen/Spline.h b/AmpGen/Spline.h index 7ceadd03b6d..3556e80b823 100644 --- a/AmpGen/Spline.h +++ b/AmpGen/Spline.h @@ -26,7 +26,7 @@ namespace AmpGen{ public: SplineTransfer(); SplineTransfer( const SplineTransfer& other ); - SplineTransfer( const size_t& address, const unsigned int& N, const double& min, const double& max ); + SplineTransfer( const size_t& address, const std::string& name, const unsigned int& N, const double& min, const double& max ); void transfer( CompiledExpressionBase* destination ) override; bool isConfigured(); void set( const unsigned int& N, AmpGen::MinuitParameter* f ); diff --git a/AmpGen/Store.h b/AmpGen/Store.h index da17cc18911..8686a91d333 100644 --- a/AmpGen/Store.h +++ b/AmpGen/Store.h @@ -13,7 +13,7 @@ namespace AmpGen { SoA, AoS }; - template class Store + template class Store { public: Store( const size_t& nEntries=0, const size_t& nFields=0) : @@ -22,34 +22,46 @@ namespace AmpGen { m_nFields(nFields), m_store(m_nBlocks * m_nFields) {} - template + template void addFunctor( const functor_type& functor, unsigned fieldsPerFunctor=0 ) { - auto vsize = fieldsPerFunctor == 0 ? functor.returnTypeSize() / sizeof(stored_type) : fieldsPerFunctor; - DEBUG("Registering: " << functor.name() << " field = " << m_nFields ); - m_index[ functor.name() ] = std::make_pair(m_nFields, vsize); - m_nFields += vsize; + if( m_index.count(functor.name()) == 0 ) + { + auto vsize = fieldsPerFunctor == 0 ? functor.returnTypeSize() / sizeof(stored_type) : fieldsPerFunctor; + DEBUG("Registering: " << functor.name() << " field = " << m_nFields ); + m_index[ functor.name() ] = std::make_pair(m_nFields, vsize); + m_nFields += vsize; + } } - - template Store( const size_t& nEntries, const std::vector& functors, const size_t& fieldsPerFunctor = 0) + template void allocate( const size_t& nEntries, const std::vector& functors, const size_t& fieldsPerFunctor = 0) { for(const auto& functor : functors) addFunctor( functor, fieldsPerFunctor); m_nEntries = nEntries; m_nBlocks = utils::aligned_size(nEntries)/utils::size::value; m_store.resize(m_nBlocks * m_nFields); } - template ::value>::type> - Store( const size_t& nEntries, const functor_type& functor, const size_t& fieldsPerFunctor=0 ) + template ::value>::type > + void allocate( const size_t& nEntries, const functor_type& functor, const size_t& fieldsPerFunctor = 0) { - addFunctor(functor); + addFunctor(functor, fieldsPerFunctor); m_nEntries = nEntries; m_nBlocks = utils::aligned_size(nEntries)/utils::size::value; m_store.resize(m_nBlocks * m_nFields); } + + template Store( const size_t& nEntries, const std::vector& functors, const size_t& fieldsPerFunctor = 0) + { + allocate(nEntries, functors, fieldsPerFunctor); + } + template ::value>::type> + Store( const size_t& nEntries, const functor_type& functor, const size_t& fieldsPerFunctor=0 ) + { + allocate( nEntries, {functor}, fieldsPerFunctor); + } inline stored_type operator[]( const size_t& index ) const { return m_store[index]; } inline stored_type& operator[]( const size_t& index ) { return m_store[index]; } - template unsigned find( const T& t ) const { return m_index.find( t.name() )->second.first; } + template unsigned find( const T& t ) const { return m_index.find( t.name() )->second.first; } inline size_t size() const { return m_nEntries; } inline size_t nBlocks() const { return m_nBlocks; } @@ -60,12 +72,13 @@ namespace AmpGen { if constexpr( align == Alignment::SoA ) return m_store[ field * m_nBlocks + index] ; else return m_store[index*m_nFields+field]; } - template + template inline const return_type get(const size_t& index, const size_t& field ) const { return utils::at( operator()( index / utils::size::value, field ), index % utils::size::value ); } inline const stored_type* data() const { return m_store.data(); } + inline stored_type* data() { return m_store.data() ;} inline stored_type& operator()(const size_t& index, const size_t& field) { if constexpr( align == Alignment::SoA ) return m_store[ field * m_nBlocks + index] ; @@ -91,7 +104,7 @@ namespace AmpGen { } } - template void update(const Store& is, const functor_type& fcn) + template void update(const Store& is, const functor_type& fcn) { auto f = m_index.find( fcn.name() ); if( f == m_index.end() ) FATAL("Expression: " << fcn.name() << " is not registed"); @@ -112,7 +125,7 @@ namespace AmpGen { fcn.batch(aligned_size(), is.nFields(), 1 , m_store.data() + p0*m_nBlocks , fcn.externBuffer().data(), is.data() ); } } - template void update( const EventList& events, const functor_type& fcn ) + template void update( const EventList& events, const functor_type& fcn ) { auto f = m_index.find( fcn.name() ); if( f == m_index.end() ) FATAL("Expression: " << fcn.name() << " is not registed"); diff --git a/AmpGen/SumPDF.h b/AmpGen/SumPDF.h index dd096cbffca..830c7d4413c 100644 --- a/AmpGen/SumPDF.h +++ b/AmpGen/SumPDF.h @@ -124,7 +124,7 @@ namespace AmpGen KeyedFunctors view; for_each( this->m_pdfs, [&view, &events]( const auto& pdf) mutable { auto eval = pdf.evaluator(events); - view.add([eval](const auto& event){ return eval(event) ; } , typeof(pdf), "" ); + view.add([eval](const auto& event){ return eval(event) ; } , type_string(pdf), "" ); } ); return view; } diff --git a/AmpGen/TreePhaseSpace.h b/AmpGen/TreePhaseSpace.h index bca2cd1da5c..3c708882f5d 100644 --- a/AmpGen/TreePhaseSpace.h +++ b/AmpGen/TreePhaseSpace.h @@ -36,17 +36,16 @@ namespace AmpGen */ class TreePhaseSpace { + public: struct Vertex { + enum Type { BW, Flat, Stable, QuasiStable}; Vertex() = default; Vertex(const Particle& particle, const double& min); - Vertex(const Particle& particle, const double& min, const double& max, const bool& isStable); + Vertex(const Particle& particle, const double& min, const double& max); double p() const; - double genBW() const; - double BW(const double& si) const; double weight() const; - double maxWeight() const; double genPdf(const Event& event) const; void generate(); void print(const unsigned& offset = 0) const; @@ -59,22 +58,20 @@ namespace AmpGen Particle particle; double min = {0}; double max = {0}; - double rhoMax = {0}; - double s = {0}; - bool isStable = {false}; - bool isBW = {true}; + double phiMin = {0}; + double phiMax = {0}; + Type type = {Type::BW}; unsigned index = {999}; double bwMass = {0}; double bwWidth = {0}; - double phiMin = {0}; - double phiMax = {0}; - double w = {0}; - double weightMax= {0}; + double s = {0}; std::shared_ptr left = {nullptr}; std::shared_ptr right = {nullptr}; TRandom3* rand = {nullptr}; std::vector indices; - TLorentzVector mom; + TLorentzVector mom; + bool isMultiBody = {false}; + PhaseSpace phsp; /// multibody phase to resort to for non two-body decomposition; }; explicit TreePhaseSpace(const EventType& type); diff --git a/AmpGen/TreeReader.h b/AmpGen/TreeReader.h index d808025d423..86bea94c1e7 100644 --- a/AmpGen/TreeReader.h +++ b/AmpGen/TreeReader.h @@ -49,6 +49,7 @@ namespace AmpGen bool operator==( const Iterator& rhs ) const { return m_position == rhs.m_position; } bool operator!=( const Iterator& rhs ) const { return m_position != rhs.m_position; } size_t operator*() const { return m_position; } + unsigned pos() const { return m_position; } }; TTree* m_tree = {nullptr}; bool m_ready = {false}; @@ -90,7 +91,7 @@ namespace AmpGen ERROR( "Branch type:" << branchType << " not recognised" ); return; } - DEBUG("Making branch with properties: [name = " << name << ", input type = " << branchType << " output type = " << typeof() << "]" ); + DEBUG("Making branch with properties: [name = " << name << ", input type = " << branchType << " output type = " << type_string() << "]" ); m_ready = false; m_branches.push_back( new_branch ); } diff --git a/AmpGen/Units.h b/AmpGen/Units.h index c7e88da4570..00b40c2ccf5 100644 --- a/AmpGen/Units.h +++ b/AmpGen/Units.h @@ -10,7 +10,16 @@ namespace AmpGen { static const double KeV = 0.001*0.001; static const double eV = 0.001*0.001*0.001; - declare_enum( Units, TeV, GeV, MeV, KeV, eV ) + static const double ms = 1000*1000; + static const double us = 1000; + static const double ns = 1; + static const double ps = 0.001; + static const double fs = 0.001*0.001; + + static const double mm = 1.0; + static const double um = 0.001; + static const double nm = 0.001*0.001; + declare_enum( Units, TeV, GeV, MeV, KeV, eV, ms, us, ns, ps, fs ) double to_double(const Units& unit ); } #endif diff --git a/AmpGen/Utilities.h b/AmpGen/Utilities.h index 791ae437a37..07ef1580995 100644 --- a/AmpGen/Utilities.h +++ b/AmpGen/Utilities.h @@ -82,7 +82,7 @@ namespace AmpGen { template RETURN_TYPE lexical_cast( const std::string& word, bool& status ) { - WARNING( "Only use specialised versions of this template (word = " << word << ", type = " << AmpGen::typeof() + WARNING( "Only use specialised versions of this template (word = " << word << ", type = " << AmpGen::type_string() << ") " ); status = 0; return RETURN_TYPE(); diff --git a/AmpGen/simd/avx2d_types.h b/AmpGen/simd/avx2d_types.h index f478f365d6f..88ab0bfdd4b 100644 --- a/AmpGen/simd/avx2d_types.h +++ b/AmpGen/simd/avx2d_types.h @@ -6,12 +6,20 @@ #include #include #include +#include + +extern "C" __m256d _ZGVcN4v_cos(__m256d x); +extern "C" __m256d _ZGVcN4v_sin(__m256d x); +extern "C" __m256d _ZGVcN4v_exp(__m256d x); +extern "C" __m256d _ZGVcN4v_log(__m256d x); +extern "C" void _ZGVdN4vvv_sincos(__m256d x, __m256i ptrs, __m256i ptrc); namespace AmpGen { namespace AVX2d { - #define stl_fallback( x ) \ - inline real_v x( const real_v& v ){ auto a = v.to_array(); return real_v( std::x(a[0]), std::x(a[1]), std::x(a[2]), std::x(a[3]) ) ; } - + + #define libmvec_alias( function_name, avx_function_name ) \ + inline real_v function_name( const real_v& v ){ return avx_function_name (v) ; } + struct real_v { __m256d data; static constexpr unsigned size = 4; @@ -25,6 +33,7 @@ namespace AmpGen { data = _mm256_loadu_pd(tmp); } real_v(const double* f ) : data( _mm256_loadu_pd( f ) ) {} + real_v(const std::array f ) : data( _mm256_loadu_pd( f.data() ) ) {} void store( double* ptr ) const { _mm256_storeu_pd( ptr, data ); } std::array to_array() const { std::array b; store( &b[0] ); return b; } double at(const unsigned i) const { return to_array()[i] ; } @@ -51,10 +60,25 @@ namespace AmpGen { inline real_v operator==( const real_v& lhs, const real_v& rhs ){ return _mm256_cmp_pd( lhs, rhs, _CMP_EQ_OS ); } inline real_v sqrt( const real_v& v ) { return _mm256_sqrt_pd(v); } inline real_v abs ( const real_v& v ) { return _mm256_andnot_pd(_mm256_set1_pd(-0.), v); } - // inline real_v sin( const real_v& v ) { return sin256_pd(v) ; } - // inline real_v cos( const real_v& v ) { return cos256_pd(v) ; } - // inline real_v tan( const real_v& v ) { real_v s; real_v c; sincos256_pd(v, (__m256*)&s, (__m256*)&c) ; return s/c; } - // inline real_v exp( const real_v& v ) { return exp256_ps(v) ; } + + libmvec_alias( sin, _ZGVcN4v_sin ) + libmvec_alias( cos, _ZGVcN4v_cos ) + libmvec_alias( exp, _ZGVcN4v_exp ) + libmvec_alias( log, _ZGVcN4v_log ) + inline void sincos( const real_v& v, real_v& s, real_v& c ) + { + __m256i sp = _mm256_add_epi64(_mm256_set1_epi64x((uint64_t)&s),_mm256_set_epi64x(24,16,8,0)); + __m256i cp = _mm256_add_epi64(_mm256_set1_epi64x((uint64_t)&c),_mm256_set_epi64x(24,16,8,0)); + _ZGVdN4vvv_sincos(v,sp,cp); + } + + inline real_v tan( const real_v& v ) + { + real_v s, c; + sincos( v, s, c ); + return s / c ; + } + inline real_v select(const real_v& mask, const real_v& a, const real_v& b ) { return _mm256_blendv_pd( b, a, mask ); } inline real_v select(const bool& mask , const real_v& a, const real_v& b ) { return mask ? a : b; } inline real_v sign ( const real_v& v){ return select( v > 0., +1., -1. ); } @@ -78,50 +102,10 @@ namespace AmpGen { return _mm256_i64gather_pd(base_addr, udouble_to_uint(offsets),sizeof(double)); } - inline void frexp(const real_v& value, real_v& mant, real_v& exponent) - { - auto arg_as_int = _mm256_castpd_si256(value); - static const real_v offset(4503599627370496.0 + 1022.0); // 2^52 + 1022.0 - static const __m256i pow2_52_i = _mm256_set1_epi64x(0x4330000000000000); // *reinterpret_cast(&pow2_52_d); - auto b = _mm256_srl_epi64(arg_as_int, _mm_cvtsi32_si128(52)); - auto c = _mm256_or_si256( b , pow2_52_i); - exponent = real_v( _mm256_castsi256_pd(c) ) - offset; - mant = _mm256_castsi256_pd(_mm256_or_si256(_mm256_and_si256 (arg_as_int, _mm256_set1_epi64x(0x000FFFFFFFFFFFFFll) ), _mm256_set1_epi64x(0x3FE0000000000000ll))); - } - inline real_v fmadd( const real_v& a, const real_v& b, const real_v& c ) { return _mm256_fmadd_pd(a, b, c); } - inline real_v log(const real_v& arg) - { - static const real_v corr = 0.693147180559945286226764; - static const real_v CL15 = 0.148197055177935105296783; - static const real_v CL13 = 0.153108178020442575739679; - static const real_v CL11 = 0.181837339521549679055568; - static const real_v CL9 = 0.22222194152736701733275; - static const real_v CL7 = 0.285714288030134544449368; - static const real_v CL5 = 0.399999999989941956712869; - static const real_v CL3 = 0.666666666666685503450651; - static const real_v CL1 = 2.0; - real_v mant, exponent; - frexp(arg, mant, exponent); - auto x = (mant - 1.) / (mant + 1.); - auto x2 = x * x; - auto p = fmadd(CL15, x2, CL13); - p = fmadd(p, x2, CL11); - p = fmadd(p, x2, CL9); - p = fmadd(p, x2, CL7); - p = fmadd(p, x2, CL5); - p = fmadd(p, x2, CL3); - p = fmadd(p, x2, CL1); - p = fmadd(p, x, corr * exponent); - return p; - } - stl_fallback( exp ) - stl_fallback( tan ) - stl_fallback( sin ) - stl_fallback( cos ) inline real_v remainder( const real_v& a, const real_v& b ){ return a - real_v(_mm256_round_pd(a/b, _MM_FROUND_TO_NEG_INF)) * b; } inline real_v fmod( const real_v& a, const real_v& b ) { @@ -189,7 +173,9 @@ namespace AmpGen { inline complex_v select(const real_v& mask, const complex_v& a, const real_v& b ) { return complex_v( select(mask, a.re, b ) , select(mask, a.im, 0.f) ); } inline complex_v select(const bool& mask , const complex_v& a, const complex_v& b ) { return mask ? a : b; } inline complex_v exp( const complex_v& v ){ - return exp( v.re) * complex_v( cos( v.im ), sin( v.im ) ); + real_v c, s; + sincos( v.im, c, s ); + return exp(v.re) * complex_v(c, s); } inline complex_v sqrt( const complex_v& v ) { diff --git a/AmpGen/simd/utils.h b/AmpGen/simd/utils.h index b10b3580c6c..d4e4cbb45b7 100644 --- a/AmpGen/simd/utils.h +++ b/AmpGen/simd/utils.h @@ -2,6 +2,7 @@ #define AMPGEN_SIMD_UTILS_H #include +#include #if ENABLE_AVX512 #include "AmpGen/simd/avx512d_types.h" @@ -11,6 +12,8 @@ #include "AmpGen/simd/avx2f_types.h" #endif + + namespace AmpGen { #if ENABLE_AVX512 namespace AVX = AVX512d; @@ -66,11 +69,12 @@ namespace AmpGen { template bool all_of( const simd_type& obj, const value_type& v ) { if constexpr( ! is_vector_type::value ) return obj == v; - else { - auto arr = obj.to_array(); - for( unsigned i = 0 ; i != size::value; ++i ) if( arr[i] != v ) return false; - return true; - } + else return _mm256_movemask_pd( obj == v ) == 0xF; + } + template bool all_of( const simd_type& obj) + { + if constexpr( ! is_vector_type::value ) return obj; + else return _mm256_movemask_pd( obj ) == 0xF; } template auto get( vtype v ) { diff --git a/CMakeLists.txt b/CMakeLists.txt index 91f484b9100..04680a05846 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,8 +12,8 @@ if(COMMAND gaudi_subdir) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp -Wno-unused-parameter -ldl") - set(AmpGen_VERSION_MAJOR "1") - set(AmpGen_VERSION_MINOR "1") + set(AmpGen_VERSION_MAJOR "2") + set(AmpGen_VERSION_MINOR "0") set(AMPGEN_CXX ${CMAKE_CXX_COMPILER} CACHE FILEPATH "This should be the path to compiler (use which c++ for macOS)" ) configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/AmpGen/Version.h.in" "${CMAKE_CURRENT_SOURCE_DIR}/AmpGen/Version.h") gaudi_add_library(AmpGen diff --git a/Standalone.cmake b/Standalone.cmake index 254d52f89af..a476fb87bd9 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -64,7 +64,7 @@ target_include_directories(AmpGen PUBLIC $ idBranches = NamedParameter("IdBranches" , std::vector() ).getVector(); bool usePIDCalib = NamedParameter("usePIDCalib" , false); bool rejectMultipleCandidates = NamedParameter("rejectMultipleCandidates", true ); - std::string cuts = vectorToString( NamedParameter("Cut","").getVector() , " && "); + std::string cuts = NamedParameter("Cut",""); EventType evtType( NamedParameter( "EventType" ).getVector() ); std::vector branches; @@ -141,14 +141,14 @@ int main( int argc, char* argv[] ) INFO("Constructing eventList"); if ( motherID != "" ) { + bool neg = motherID[0] == '-'; INFO( "Converting " << evtType.mother() << " " << eventsToTake.size() << " " << evts.size() ); - in_tree->SetBranchStatus( "*", 0 ); + TreeReader tr( in_tree ); int id = 0; - in_tree->SetBranchStatus( motherID.c_str() ); - in_tree->SetBranchAddress( motherID.c_str(), &id ); + tr.setBranch( neg ? motherID.substr(1, motherID.size() -1 ) : motherID, & id ); for ( unsigned int i = 0; i < eventsToTake.size(); ++i ) { - in_tree->GetEntry( eventsToTake[i] ); - if ( id < 0 ) invertParity( evts[i] , evtType.size() ); + tr.getEntry(eventsToTake[i] ); + if ( neg ? id > 0 : id < 0 ) invertParity( evts[i] , evtType.size() ); } } diff --git a/apps/Fitter.cpp b/apps/Fitter.cpp index 5159a789cd7..52ef74f1ad1 100644 --- a/apps/Fitter.cpp +++ b/apps/Fitter.cpp @@ -87,7 +87,7 @@ void addExtendedTerms( Minimiser& mini, SIGPDF& pdf, MinuitParameterSet& mps ) template FitResult* doFit( PDF&& pdf, EventList& data, EventList& mc, MinuitParameterSet& MPS ) { - INFO( "Type = " << typeof() ); + INFO( "Type = " << type_string() ); auto time_wall = std::chrono::high_resolution_clock::now(); auto time = std::clock(); pdf.setEvents( data ); diff --git a/apps/Generator.cpp b/apps/Generator.cpp index 3abf40b7bb6..a8f77720b72 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -31,39 +31,98 @@ #include "AmpGen/ParticlePropertiesList.h" #include "AmpGen/AddCPConjugate.h" +#if ENABLE_AVX + #include "AmpGen/EventListSIMD.h" + using EventList_t = AmpGen::EventListSIMD; +#else + #include "AmpGen/EventList.h" + using EventList_t = AmpGen::EventList; +#endif + using namespace AmpGen; -namespace AmpGen { make_enum(generatorType, CoherentSum, PolarisedSum, FixedLib, RGenerator, TreePhaseSpace) } +namespace AmpGen { + make_enum(pdfTypes, CoherentSum, PolarisedSum, FixedLib) + make_enum(phspTypes, PhaseSpace, RecursivePhaseSpace, TreePhaseSpace) +} -struct FixedLibPDF { +struct FixedLibPDF +{ void* lib = {nullptr}; - AmpGen::DynamicFCN PDF; - + DynamicFCN PDF; + void debug( const Event& event) {}; void prepare(){}; void setEvents( AmpGen::EventList& evts ){}; double operator()( const AmpGen::Event& evt ) const { return PDF( evt, 1 ); } + double operator()( const double* evt, const unsigned& index ) + { + return PDF(evt, 1 ); + } FixedLibPDF( const std::string& lib ) { void* handle = dlopen( lib.c_str(), RTLD_NOW ); if ( handle == nullptr ) ERROR( dlerror() ); - PDF = AmpGen::DynamicFCN( handle, "FCN" ); + PDF = DynamicFCN( handle, "FCN" ); } size_t size() { return 0; } void reset( const bool& flag = false ){}; }; -template - void GenerateEvents( EventList& events - , PDF_TYPE& pdf - , PRIOR_TYPE& prior + +template Particle getTopology(const pdf_t& pdf) +{ + if constexpr( std::is_same::value ) + { + FATAL("Cannot deduce decay topology from a compiled library, check generator options"); + } + else return pdf.matrixElements()[0].decayTree.quasiStableTree(); +} + +template std::vector getDecayChains( const pdf_t& pdf ) +{ + if constexpr( std::is_same::value ) + { + FATAL("Cannot deduce decay topology from a compiled library, check generator options"); + } + else { + std::vector channels; + for( auto& chain : pdf.matrixElements() ) channels.push_back( chain.decayTree ); + return channels; + } +} + +template void generateEvents( EventList& events + , pdf_t& pdf + , const phspTypes& phsp_type , const size_t& nEvents , const size_t& blockSize - , TRandom* rndm ) + , TRandom* rndm + , const bool& normalise = true ) { - Generator signalGenerator( prior ); - signalGenerator.setRandom( rndm); - signalGenerator.setBlockSize( blockSize ); - signalGenerator.fillEventList( pdf, events, nEvents ); + if( phsp_type == phspTypes::PhaseSpace ) + { + Generator signalGenerator(events.eventType(), rndm); + signalGenerator.setBlockSize(blockSize); +// signalGenerator.setNormFlag(normalise); + signalGenerator.fillEventList(pdf, events, nEvents ); + } + else if( phsp_type == phspTypes::RecursivePhaseSpace ) + { + Generator signalGenerator( getTopology(pdf), events.eventType(), rndm ); + signalGenerator.setBlockSize(blockSize); +// signalGenerator.setNormFlag(normalise); + signalGenerator.fillEventList(pdf, events, nEvents); + } + else if( phsp_type == phspTypes::TreePhaseSpace ) + { + Generator signalGenerator(getDecayChains(pdf), events.eventType(), rndm); + signalGenerator.setBlockSize(blockSize); +// signalGenerator.setNormFlag(normalise); + signalGenerator.fillEventList(pdf, events, nEvents ); + } + else { + FATAL("Phase space configuration: " << phsp_type << " is not supported"); + } } @@ -72,16 +131,17 @@ int main( int argc, char** argv ) OptionsParser::setArgs( argc, argv ); size_t nEvents = NamedParameter ("nEvents" , 1, "Total number of events to generate" ); - size_t blockSize = NamedParameter ("BlockSize", 100000, "Number of events to generate per block" ); + size_t blockSize = NamedParameter ("BlockSize", 5000000, "Number of events to generate per block" ); int seed = NamedParameter ("Seed" , 0, "Random seed used in event Generation" ); std::string outfile = NamedParameter("Output" , "Generate_Output.root" , "Name of output file" ); - auto genType = NamedParameter( "Type", generatorType::CoherentSum, optionalHelpString("Generator configuration to use:", + auto pdfType = NamedParameter( "Type", pdfTypes::CoherentSum, optionalHelpString("Generator configuration to use:", { {"CoherentSum" , "Full phase-space generator with (pseudo)scalar amplitude"} , {"PolarisedSum" , "Full phase-space generator with particles carrying spin in the initial/final states"} - , {"FixedLib" , "Full phase-space generator with an amplitude from a precompiled library"} - , {"RGenerator" , "Recursive phase-space generator for intermediate (quasi)stable states such as the D-mesons"} - , {"TreePhaseSpace" , "Recursive phase-space generator with generic handling of intermediate states."} } ) ); - + , {"FixedLib" , "Full phase-space generator with an amplitude from a precompiled library"}} ) ); + auto phspType = NamedParameter( "PhaseSpace", phspTypes::PhaseSpace, optionalHelpString("Phase-space generator to use:", + { {"CoherentSum" , "Full phase-space generator with (pseudo)scalar amplitude"} + , {"PolarisedSum" , "Full phase-space generator with particles carrying spin in the initial/final states"} + , {"FixedLib" , "Full phase-space generator with an amplitude from a precompiled library"}} ) ); std::string lib = NamedParameter("Library","","Name of library to use for a fixed library generation"); size_t nBins = NamedParameter ("nBins" ,100, "Number of bins for monitoring plots." ); @@ -122,40 +182,20 @@ int main( int argc, char** argv ) INFO("Generating events with type = " << eventType ); - if ( genType == generatorType::CoherentSum ) { - CoherentSum sig( eventType, MPS ); - PhaseSpace phsp(eventType,&rand); - GenerateEvents( accepted, sig, phsp , nEvents, blockSize, &rand ); - } - else if ( genType == generatorType::PolarisedSum ){ - PolarisedSum sig( eventType, MPS ); - RecursivePhaseSpace phsp( sig.matrixElements()[0].decayTree.quasiStableTree() , eventType, &rand ); - GenerateEvents( accepted, sig, phsp, nEvents, blockSize, &rand ); - } - else if ( genType == generatorType::RGenerator ) { - CoherentSum sig( eventType, MPS, "" ); - Generator signalGenerator( sig[0].decayTree.quasiStableTree(), eventType ); - signalGenerator.setRandom( &rand ); - signalGenerator.fillEventList( sig, accepted, nEvents ); + if ( pdfType == pdfTypes::CoherentSum ){ + CoherentSum pdf( eventType, MPS); + generateEvents(accepted, pdf, phspType , nEvents, blockSize, &rand ); } - else if ( genType == generatorType::TreePhaseSpace ) { - PolarisedSum sig( eventType, MPS); - std::vector channels; - for( auto& chain : sig.matrixElements() ) channels.push_back( chain.decayTree ); - Generator signalGenerator(channels, eventType, &rand); - signalGenerator.setRandom( &rand ); - signalGenerator.fillEventList( sig, accepted, nEvents ); + else if ( pdfType == pdfTypes::PolarisedSum ){ + PolarisedSum pdf(eventType, MPS); + generateEvents( accepted, pdf, phspType, nEvents, blockSize, &rand ); } - else if ( genType == generatorType::FixedLib ) { - Generator<> signalGenerator( eventType ); - signalGenerator.setRandom( &rand ); - signalGenerator.setBlockSize( blockSize ); - signalGenerator.setNormFlag( false ); - FixedLibPDF pdf( lib ); - signalGenerator.fillEventList( pdf, accepted, nEvents ); - } + // else if ( pdfType == pdfTypes::FixedLib ){ + // FixedLibPDF pdf(lib); + // generateEvents( accepted, pdf, phspType, nEvents, blockSize, &rand, false ); + // } else { - FATAL("Did not recognise configuration: " << genType ); + FATAL("Did not recognise configuration: " << pdfType ); } if( accepted.size() == 0 ) return -1; TFile* f = TFile::Open( outfile.c_str(), "RECREATE" ); diff --git a/examples/QcGenerator.cpp b/examples/QcGenerator.cpp index f40a90331e7..7a410e5ab45 100644 --- a/examples/QcGenerator.cpp +++ b/examples/QcGenerator.cpp @@ -102,7 +102,7 @@ template struct normalised_pdf { norm = sqrt(yc.bf(type)/n); if( it != nullptr ) norm *= exp( 1i * it->mean() * M_PI/180. ); pc.stop(); - INFO(type << " Time to construct: " << pc << "[ms], norm = " << norm << " " << typeof() ); + INFO(type << " Time to construct: " << pc << "[ms], norm = " << norm << " " << type_string() ); } complex_t operator()(const Event& event){ return norm * pdf.getValNoCache(event); } }; diff --git a/src/ASTResolver.cpp b/src/ASTResolver.cpp index 2b6785aba3f..6118fb62795 100644 --- a/src/ASTResolver.cpp +++ b/src/ASTResolver.cpp @@ -19,7 +19,6 @@ ASTResolver::ASTResolver(const std::map& evtMap, m_nParameters(0) { m_enable_cuda = NamedParameter("UseCUDA",false); - m_enable_avx = NamedParameter("UseAVX",false); m_enable_compileTimeConstants = NamedParameter("ASTResolver::CompileTimeConstants", false); } @@ -69,7 +68,7 @@ template <> void ASTResolver::resolve( const SubTree& subTree ) template <> void ASTResolver::resolve( const Spline& spline ) { if( m_resolvedParameters.count( &spline) != 0 ) return ; - auto address = addCacheFunction(spline.m_name,spline.m_nKnots,spline.m_min,spline.m_max); + auto address = addCacheFunction(spline.m_name, spline.m_nKnots, spline.m_min, spline.m_max); addResolvedParameter( &spline, address ); addResolvedParameter( spline.m_points.top().get(), address ); auto splineTransfer = dynamic_cast( m_cacheFunctions[spline.m_name].get() ); diff --git a/src/CacheTransfer.cpp b/src/CacheTransfer.cpp index 0c8aa6166a2..0963b0d305b 100644 --- a/src/CacheTransfer.cpp +++ b/src/CacheTransfer.cpp @@ -11,10 +11,11 @@ using namespace AmpGen; CacheTransfer::CacheTransfer() = default; -CacheTransfer::CacheTransfer( const size_t& address, const double& value, const size_t& size ) : +CacheTransfer::CacheTransfer( const size_t& address, const std::string& name, const double& value, const size_t& size ) : m_address(address), m_size(size), - m_value(value) + m_value(value), + m_name(name) { } @@ -25,7 +26,7 @@ void CacheTransfer::transfer( CompiledExpressionBase* destination ) void CacheTransfer::print() const { - INFO( m_address << " " << m_value ) ; + INFO( m_address << " " << m_value << " " << m_name ) ; } void ParameterTransfer::transfer( CompiledExpressionBase* destination ) @@ -33,14 +34,13 @@ void ParameterTransfer::transfer( CompiledExpressionBase* destination ) destination->setExternal( m_source->mean(), m_address ); } -ParameterTransfer::ParameterTransfer( const size_t& address, MinuitParameter* source ) - : CacheTransfer(address, source->mean(), 1), +ParameterTransfer::ParameterTransfer(const size_t& address, const std::string& name, MinuitParameter* source ) + : CacheTransfer(address, name, source->mean(), 1), m_source( source ) { } void ParameterTransfer::print() const { - std::cout << this << " " << m_source->name() << " " << m_address << std::endl; - INFO( "Source: " << m_source->name() << " address = " << m_address ); + INFO( "Source: " << m_source->name() << " address = " << m_address << " value = " << m_source->mean() ); } diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index e3240a318d1..2139023116d 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -263,7 +263,7 @@ void CoherentSum::setEvents( const EventList_type& list ) for( auto& me : m_matrixElements ){ DEBUG("Registering: " << me.name() ) ; } if( m_ownEvents && m_events != nullptr ) delete m_events; m_events = &list; - m_cache = Store( m_events->size(), m_matrixElements ); + m_cache . allocate( m_events->size(), m_matrixElements ); } @@ -341,6 +341,13 @@ float_v CoherentSum::operator()( const float_v* /*evt*/, const unsigned block ) return (m_weight/m_norm ) * utils::norm(value); } +#if ENABLE_AVX +double CoherentSum::operator()( const double* /*evt*/, const unsigned block ) const +{ + return operator()((const float_v*)nullptr, block / utils::size::value ).at( block % utils::size::value ); +} +#endif + std::function CoherentSum::evaluator(const EventList_type* ievents) const { auto events = ievents == nullptr ? m_integrator.events() : ievents; diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index d9c10a323ff..864f13f3389 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -144,7 +144,7 @@ void CompiledExpressionBase::compile(const std::string& fname) void CompiledExpressionBase::addDebug( std::ostream& stream ) const { stream << "#include\n"; - stream << "extern \"C\" std::vector() << " >> " + stream << "extern \"C\" std::vector() << " >> " << m_progName << "_DB(" << fcnSignature() << "){\n"; for ( auto& dep : m_debugSubexpressions ) { std::string rt = "auto v" + std::to_string(dep.first) + " = " + dep.second.to_string(m_resolver.get()) +";"; @@ -156,8 +156,8 @@ void CompiledExpressionBase::addDebug( std::ostream& stream ) const const auto expression = m_db[i].second; stream << std::endl << "{\"" << m_db[i].first << "\","; if ( expression.to_string(m_resolver.get()) != "NULL" ) - stream << typeof() << "("<< expression.to_string(m_resolver.get()) << ")}" << comma; - else stream << typeof() << "(-999.,0.)}" << comma ; + stream << type_string() << "("<< expression.to_string(m_resolver.get()) << ")}" << comma; + else stream << type_string() << "(-999.,0.)}" << comma ; } } diff --git a/src/EventList.cpp b/src/EventList.cpp index 86727861ad8..8fe00dcb738 100644 --- a/src/EventList.cpp +++ b/src/EventList.cpp @@ -84,6 +84,7 @@ void EventList::loadFromTree( TTree* tree, const ArgumentPack& args ) tree->SetBranchStatus( "*", 0 ); TreeReader tr( tree ); bool hasEnergy = branches.size() == 0 || branches.size() == 4 * m_eventType.size(); // if the energy of the particle has been explicitly specified // + std::vector ids( m_eventType.size() ); if( branches.size() != 0 ) { DEBUG("Branches = [" << vectorToString(branches, ", ") << "]" ); @@ -93,15 +94,17 @@ void EventList::loadFromTree( TTree* tree, const ArgumentPack& args ) DEBUG("Setting branch: " << branches[p] << " pos: " << pos << " fmt = " << inv_map( eventFormat, pos, "NOT FOUND" ) << " has energy? " << hasEnergy ); tr.setBranch( branches[p], &(temp[pos]) ); } - auto pos = eventFormat.size(); - for( const auto& branch : extraBranches ) m_extensions[branch] = pos++; + if( idBranches.size() != 0 ) + { + if( idBranches.size() != m_eventType.size() ) FATAL("Number of ID branches should be number of final state particles"); + for( int i = 0; i != ids.size(); ++i ) tr.setBranch( idBranches[i], ids.data() + i); + } } else for ( auto& branch : eventFormat ) tr.setBranch( branch.first, &(temp[branch.second]) ); - std::vector ids( m_eventType.size() ); - if( idBranches.size() != 0 ) - { - if( idBranches.size() != m_eventType.size() ){ FATAL("Number of ID branches should be number of final state particles"); } - for( int i = 0; i != ids.size(); ++i ) tr.setBranch( idBranches[i], ids.data() + i); + auto pos = eventFormat.size(); + for( const auto& branch : extraBranches ){ + tr.setBranch( branch, &(temp[pos]) ); + m_extensions[branch] = pos++; } if( getGenPdf ) tr.setBranch( "genPdf", temp.pGenPdf() ); if( weightBranch != "" ) tr.setBranch( weightBranch, temp.pWeight() ); @@ -121,14 +124,14 @@ void EventList::loadFromTree( TTree* tree, const ArgumentPack& args ) auto automaticOrdering = m_eventType.automaticOrdering(); for (const auto& evt : tr) { if( inputUnits != Units::GeV ) for( unsigned k = 0; k != eventFormat.size(); ++k ) temp[k] *= to_double(inputUnits); - if( idBranches.size() != 0 ) automaticOrdering(temp, ids); + if( idBranches.size() != 0 && !automaticOrdering(temp, ids) ) + WARNING("Failed to order event: " << evt ); if( applySym ) symmetriser(temp); if( ! hasEnergy ){ for( unsigned int k = 0 ; k != m_eventType.size(); ++k ) temp[4*k + 3] = sqrt( m_eventType.mass(k) * m_eventType.mass(k) + temp[4*k+0]*temp[4*k+0] + temp[4*k+1]*temp[4*k+1] + temp[4*k+2]*temp[4*k+2] ); } - temp.setIndex( m_data.size() ); - m_data.push_back( temp ); + push_back( temp ); } read_time.stop(); INFO("Time to read tree = " << read_time << "[ms]; nEntries = " << size() ); @@ -205,7 +208,7 @@ double EventList::integral() const void EventList::add( const EventList& evts ) { - for ( auto& evt : evts ) m_data.push_back( evt ); + for ( auto& evt : evts ) push_back( evt ); } void EventList::clear() @@ -218,3 +221,26 @@ void EventList::erase(const std::vector::iterator& begin, { m_data.erase( begin, end ); } + +void EventList::reserve( const size_t& size ) +{ + m_data.reserve( size ); +} + +void EventList::resize ( const size_t& size ) +{ + m_data.resize(size); + for( unsigned int i = 0 ; i != size; ++i ) m_data[i].setIndex(i) ; +} + +void EventList::push_back( const Event& evt ) +{ + m_data.push_back( evt ); + m_data.rbegin()->setIndex(m_data.size()-1); +} + +void EventList::emplace_back( const Event& evt) +{ + m_data.emplace_back(evt) ; + m_data.rbegin()->setIndex(m_data.size()-1); +} diff --git a/src/EventListSIMD.cpp b/src/EventListSIMD.cpp index 2ba7040bcb4..8a1178a2ad6 100644 --- a/src/EventListSIMD.cpp +++ b/src/EventListSIMD.cpp @@ -35,7 +35,9 @@ using namespace AmpGen; // ENABLE_DEBUG(EventListSIMD) -EventListSIMD::EventListSIMD( const EventType& type ) : m_eventType( type ) {} +EventListSIMD::EventListSIMD( const EventType& type ) : + m_data(0, type.eventSize() ), + m_eventType( type ) {} void EventListSIMD::loadFromFile( const std::string& fname, const ArgumentPack& args ) { @@ -108,10 +110,8 @@ void EventListSIMD::loadFromTree( TTree* tree, const ArgumentPack& args ) bool hasEventList = entryList.size() != 0; size_t nEvents = hasEventList ? entryList.size() : tree->GetEntries(); std::array buffer; - - m_data = Store(nEvents, m_eventType.eventSize() ); - m_weights.resize( m_data.nBlocks() ); - m_genPDF.resize( m_data.nBlocks() ); + + resize( nEvents ); auto symmetriser = m_eventType.symmetriser(); for ( unsigned int block = 0; block < m_data.nBlocks(); ++block ) { @@ -135,10 +135,7 @@ void EventListSIMD::loadFromTree( TTree* tree, const ArgumentPack& args ) EventListSIMD::EventListSIMD( const EventList& other ) : EventListSIMD( other.eventType() ) { - m_data = Store(other.size(), m_eventType.eventSize() ); - DEBUG("Converting EventList -> EventListSIMD, allocate: " << m_data.size() << " events in " << m_data.nBlocks() << " with: " << m_data.nFields() << " fields"); - m_weights.resize( m_data.nBlocks() ); - m_genPDF.resize ( m_data.nBlocks() ); + resize( other.size() ); for( unsigned block = 0 ; block != m_data.nBlocks(); block++ ) { for( unsigned j = 0 ; j != m_data.nFields(); ++j ) diff --git a/src/EventType.cpp b/src/EventType.cpp index 9adc9b788a8..1bace03da37 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -105,7 +105,7 @@ void EventType::extendEventType( const std::string& branch ) { m_eventTypeExtensions.push_back(branch); } -std::pair EventType::minmax( const std::vector& indices, bool isGeV ) const +std::pair EventType::minmax( const std::vector& indices) const { std::vector ivec( size() ); std::iota( ivec.begin(), ivec.end(), 0 ); @@ -114,7 +114,7 @@ std::pair EventType::minmax( const std::vector& indice double max = motherMass(); for ( auto& x : ivec ) if ( std::find( indices.begin(), indices.end(), x ) == indices.end() ) max -= mass( x ); - return std::pair(min*min, max*max); + return std::pair(min, max); } std::pair EventType::count(const unsigned& index) const { @@ -180,19 +180,19 @@ std::vector EventType::defaultProjections(const unsigned& nBins) con Projection EventType::projection(const unsigned& nBins, const std::vector& indices, const std::string& observable) const { bool useRootLabelling = NamedParameter("EventType::UseRootTEX", false ); - auto mm = minmax(indices, true); + auto mm = minmax(indices); std::string gevcccc = useRootLabelling ? "GeV^{2}/c^{4}" : "\\mathrm{GeV}^{2}/c^{4}"; std::string gevcc = useRootLabelling ? "GeV/c^{2}" : "\\mathrm{GeV}/c^{2}"; if( observable == "mass2" ) return Projection( [indices]( const Event& evt ) { return evt.s( indices ); }, "s" + vectorToString( indices ), "s_{" + label( indices ) + "}", nBins, - ( mm.first - 0.05 ) , ( mm.second + 0.05 ) , gevcccc ); + ( mm.first * mm.first - 0.05 ) , ( mm.second * mm.second + 0.05 ) , gevcccc ); else if( observable == "mass" ){ return Projection( [indices]( const Event& evt ) { return sqrt( evt.s( indices ) ); }, "m" + vectorToString( indices ), "m_{" + label( indices ) + "}", nBins, - mm.first > 0.05 ? sqrt(mm.first - 0.05) :0 , sqrt( mm.second + 0.05 ) , gevcc ); + mm.first > 0.05 ? mm.first - 0.05 :0 , mm.second + 0.05, gevcc ); } return Projection(); } @@ -242,7 +242,7 @@ std::function EventType::symmetriser() const }; } -std::function&)> EventType::automaticOrdering() const +std::function&)> EventType::automaticOrdering() const { std::vector ids; for( unsigned i = 0 ; i != m_particleNames.size(); ++i ) ids.push_back( ParticleProperties::get(m_particleNames[i])->pdgID() ); @@ -259,12 +259,14 @@ std::function&)> EventType::automaticOrderin return std::all_of( std::begin(used), std::end(used), [](auto b) { return b; } ) ; }; - return [ids, matches](auto& event, const auto& actual_ids) -> void { + return [ids, matches](auto& event, const auto& actual_ids) -> bool { std::vector new_addresses( ids.size(), 999 ); int sgn = +1; if( matches(ids, actual_ids ) ) sgn = +1; else if( matches(ids, actual_ids, -1 ) ) sgn = -1; - else { FATAL("Ids: " << vectorToString(actual_ids, " ") << " do not match either particle or antiparticle ["<< vectorToString(ids, " ") << "]" );} + else { ERROR("Ids: " << vectorToString(actual_ids, " ") << " do not match either particle or antiparticle ["<< vectorToString(ids, " ") << "]" ); + return false; + } for( unsigned i = 0 ; i != ids.size(); ++i ) { @@ -274,6 +276,7 @@ std::function&)> EventType::automaticOrderin } } event.reorder( new_addresses ); + return true; }; } diff --git a/src/Expression.cpp b/src/Expression.cpp index 1584bcb9621..f0ec105523c 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -56,12 +56,12 @@ std::string Constant::to_string(const ASTResolver* resolver) const { str.erase ( str.find_last_not_of('0') + 1, std::string::npos ); return str; }; - std::string complex_type = typeof(); + std::string complex_type = type_string(); std::string literalSuffix = ""; if( resolver != nullptr && (resolver->enableCuda() || resolver->enableAVX()) ) { literalSuffix = "f"; - complex_type = typeof(); + complex_type = type_string(); } return std::imag(m_value) == 0 ? "(" + rounded_string(std::real(m_value)) +literalSuffix + ")" : complex_type +"("+rounded_string(std::real(m_value))+literalSuffix+","+rounded_string(std::imag(m_value))+literalSuffix+")"; @@ -326,8 +326,8 @@ ComplexParameter::ComplexParameter( const Parameter& real, const Parameter& imag std::string ComplexParameter::to_string(const ASTResolver* resolver) const { - std::string complex_type = typeof(); - if( resolver != nullptr && (resolver->enableCuda() || resolver->enableAVX()) ) complex_type = typeof(); + std::string complex_type = type_string(); + if( resolver != nullptr && (resolver->enableCuda() || resolver->enableAVX()) ) complex_type = type_string(); return complex_type + "(" + m_real.to_string(resolver) + ", " + m_imag.to_string(resolver) +")"; } diff --git a/src/ExpressionParser.cpp b/src/ExpressionParser.cpp index a214c9a6af1..5b230478dbb 100644 --- a/src/ExpressionParser.cpp +++ b/src/ExpressionParser.cpp @@ -154,11 +154,9 @@ Expression ExpressionParser::processEndPoint( const std::string& name, const Min bool status = true; double value = lexical_cast( name, status ); if ( status == true ) return value; - if ( name == "PI" ) return M_PI; - if ( name == "pi" ) return M_PI; + if ( name == "PI" || name == "pi" || name == "M_PI" ) return M_PI; if ( name == "e" ) return std::exp(1); - if ( name == "I" ) return complex_t( 0, 1 ); - if ( name == "i" ) return complex_t( 0, 1 ); + if ( name == "I" || name == "i" ) return complex_t( 0, 1 ); if ( mps != nullptr ) { auto it = mps->find(name); if ( it != nullptr ) return MinuitParameterLink( it ); @@ -174,9 +172,13 @@ Expression ExpressionParser::processEndPoint( const std::string& name, const Min } MinuitParameterLink::MinuitParameterLink( MinuitParameter* param ) : m_parameter( param ) {} + std::string MinuitParameterLink::to_string(const ASTResolver* resolver) const { - return resolver == nullptr ? m_parameter->name() : resolver->resolvedParameter(this); + if( resolver == nullptr ) return m_parameter->name(); + if( resolver->enableCompileConstants() && m_parameter != nullptr && m_parameter->flag () == Flag::CompileTimeConstant ) + return std::to_string( m_parameter->mean() ); + return resolver->resolvedParameter(this); } std::string MinuitParameterLink::name() const { @@ -185,7 +187,7 @@ std::string MinuitParameterLink::name() const { void MinuitParameterLink::resolve( ASTResolver& resolver ) const { - resolver.resolve(*this); + if( m_parameter->flag() != Flag::CompileTimeConstant ) resolver.resolve(*this); } complex_t MinuitParameterLink::operator()() const diff --git a/src/Kinematics.cpp b/src/Kinematics.cpp index 937969f1097..8446b000063 100644 --- a/src/Kinematics.cpp +++ b/src/Kinematics.cpp @@ -155,9 +155,7 @@ void AmpGen::boost( Event& evt, const std::tuple& n, con void AmpGen::rotate( Event& evt, const std::tuple& n, const double& v ) { - double nx = std::get<0>( n ); - double ny = std::get<1>( n ); - double nz = std::get<2>( n ); + auto& [nx,ny,nz ] = n; double cv = cos(v); double sv = sin(v); double norm = sqrt( nx * nx + ny * ny + nz * nz ); diff --git a/src/Lineshapes/BW.cpp b/src/Lineshapes/BW.cpp index 14fe2e6ea72..3b2468100b6 100644 --- a/src/Lineshapes/BW.cpp +++ b/src/Lineshapes/BW.cpp @@ -29,7 +29,7 @@ DEFINE_LINESHAPE( FormFactor ) if ( lineshapeModifier == "BL" ) FormFactor = sqrt( BlattWeisskopf( q2 * radius * radius, Lp ) ); if ( lineshapeModifier == "NFF" ) FormFactor = 1; if ( lineshapeModifier == "BELLE2018" ) FormFactor = sqrt( BlattWeisskopf_Norm( q2 * radius * radius, q20 * radius * radius, Lp ) ); - + if( L != 0 ){ ADD_DEBUG( q2 , dbexpressions ); ADD_DEBUG( radius , dbexpressions ); @@ -69,9 +69,13 @@ DEFINE_LINESHAPE( BW ) Expression FormFactor = sqrt( BlattWeisskopf_Norm( q2 * radius * radius, 0, L ) ); if ( lineshapeModifier == "BL" ) FormFactor = sqrt( BlattWeisskopf( q2 * radius * radius, L ) ); if ( lineshapeModifier == "BELLE2018" ) FormFactor = sqrt( BlattWeisskopf_Norm( q2 * radius * radius, q20 * radius * radius, L ) ); + if ( lineshapeModifier == "NFF") FormFactor = 1; Expression runningWidth = width( s_cse, s1, s2, mass, width0, radius, L, dbexpressions ); const Expression BW = FormFactor / ( mass * mass - s_cse -1i * mass * runningWidth ); const Expression kf = kFactor( mass, width0, dbexpressions ); + ADD_DEBUG( s_cse, dbexpressions ); + ADD_DEBUG( s1, dbexpressions ); + ADD_DEBUG( s2, dbexpressions ); ADD_DEBUG( FormFactor, dbexpressions ); ADD_DEBUG( runningWidth, dbexpressions ); ADD_DEBUG( BW, dbexpressions ); diff --git a/src/PhaseSpace.cpp b/src/PhaseSpace.cpp index c63be198602..0722b162d2c 100644 --- a/src/PhaseSpace.cpp +++ b/src/PhaseSpace.cpp @@ -63,8 +63,10 @@ Event PhaseSpace::makeEvent() } } while ( wt < m_rand->Rndm() ); - rt.set(0, { 0, pd[0], 0, sqrt( pd[0] * pd[0] + m_mass[0] * m_mass[0] )} ); - + rt[0] = 0; + rt[1] = pd[0]; + rt[2] = 0; + rt[3] = sqrt( pd[0] * pd[0] + m_mass[0] * m_mass[0] ); for(size_t i = 1 ; i != m_nt ; ++i ){ rt.set( i, { 0, -pd[i-1], 0, sqrt( pd[i-1] * pd[i-1] + m_mass[i] * m_mass[i] ) } ); double cZ = 2 * m_rand->Rndm() - 1; @@ -72,24 +74,17 @@ Event PhaseSpace::makeEvent() double angY = 2 * M_PI * m_rand->Rndm(); double cY = cos(angY); double sY = sin(angY); + double beta = (i == m_nt-1) ? 0 : pd[i] / sqrt( pd[i] * pd[i] + invMas[i] * invMas[i] ); + double gamma = (i == m_nt-1) ? 1 : 1./sqrt( 1 - beta*beta); for (size_t j = 0; j <= i; j++ ) { double x = rt[4*j+0]; double y = rt[4*j+1]; double z = rt[4*j+2]; - rt[4*j+0] = cZ * x - sZ * y; - rt[4*j+1] = sZ * x + cZ * y; - x = rt[4*j+0]; - rt[4*j+0] = cY * x - sY * z; - rt[4*j+2] = sY * x + cY * z; - } - if ( i == ( m_nt - 1 ) ) break; - double beta = pd[i] / sqrt( pd[i] * pd[i] + invMas[i] * invMas[i] ); - double gamma = 1./sqrt( 1 - beta*beta); - for (size_t j = 0; j <= i; j++ ){ - double E = rt[4*j+3]; - double py = rt[4*j+1]; - rt[4*j+1] = gamma*( py + beta * E ); - rt[4*j+3] = gamma*( E + beta * py ); + double E = rt[4*j+3]; + rt[4*j+0] = cY * (cZ * x - sZ * y ) - sY * z; + rt[4*j+1] = gamma*( sZ * x + cZ * y + beta * E ); + rt[4*j+2] = sY * (cZ * x - sZ * y ) + cY * z; + rt[4*j+3] = gamma*( E + beta * (sZ *x + cZ*y) ); } } rt.setGenPdf( 1 ); diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index bc2211757ed..3796544f40b 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -76,7 +76,7 @@ PolarisedSum::PolarisedSum(const EventType& type, Tensor thisExpression( Tensor::dim(polStates.size()) ); auto& [p, coupling] = protoAmps[i]; DebugSymbols syms; - for(unsigned j = 0; j != polStates.size(); ++j) thisExpression[j] = make_cse( p.getExpression(&syms, polStates[j] ) ); + for(unsigned j = 0; j != polStates.size(); ++j) thisExpression[j] = make_cse( p.getExpression(j == 0 ? &syms: nullptr, polStates[j] ) ); m_matrixElements[i] = TransitionMatrix( p, coupling, @@ -85,7 +85,9 @@ PolarisedSum::PolarisedSum(const EventType& type, p.decayDescriptor(), this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,this->m_mps ) ); CompilerWrapper().compile( m_matrixElements[i] ); - }); + m_matrixElements[i].size = thisExpression.size(); + } + ); } } if ( stype == spaceType::flavour ) @@ -201,8 +203,8 @@ void PolarisedSum::prepare() if( m_integrator.isReady() ) updateNorms(); std::for_each( m_matrixElements.begin(), m_matrixElements.end(), resetFlags ); // if( m_nCalls % 10000 == 0 ) debug_norm(); - DEBUG( "m_pdfCache[0] = " << m_pdfCache[0] << " w/o caching = " << (m_weight/m_norm) * getValNoCache(m_events->at(0))); m_pdfCache.update(m_cache, m_probExpression); + DEBUG( "m_pdfCache[0] = " << m_pdfCache[0] << " w/o caching = " << (m_weight/m_norm) * getValNoCache(m_events->at(0))); m_nCalls++; } @@ -211,6 +213,14 @@ float_v PolarisedSum::operator()( const float_v*, const unsigned index ) const return ( m_weight / m_norm ) * m_pdfCache[index]; } +#if ENABLE_AVX +double PolarisedSum::operator()( const double*, const unsigned index ) const +{ + return operator()((const float_v*)nullptr, index / utils::size::value ).at( index % utils::size::value ); +} +#endif + + void PolarisedSum::debug_norm() { double norm_slow = 0; @@ -225,8 +235,8 @@ void PolarisedSum::setEvents( EventList_type& events ) reset(); if( m_events != nullptr && m_ownEvents ) delete m_events; m_events = &events; - m_cache = Store(m_events->size(), m_matrixElements, m_dim.first * m_dim.second ); - m_pdfCache = Store(m_events->size(), m_probExpression ); + m_cache . allocate( m_events->size(), m_matrixElements, m_dim.first * m_dim.second ); + m_pdfCache . allocate( m_events->size(), m_probExpression); } void PolarisedSum::setMC( EventList_type& events ) @@ -268,6 +278,7 @@ real_t PolarisedSum::operator()(const Event& evt) const return utils::at( m_pdfCache[ evt.index() / utils::size::value ], evt.index() % utils::size::value ); } + double PolarisedSum::norm() const { return m_norm; @@ -317,8 +328,9 @@ void PolarisedSum::debug(const Event& evt) std::vector this_cache; for(unsigned i = 0 ; i != tsize; ++i ) this_cache.emplace_back( m_cache(evt.index() / utils::size::value, j*tsize + i) ); INFO( m_matrixElements[j].decayDescriptor() << " " << vectorToString( this_cache, " ") ); + if( m_debug ) m_matrixElements[0].debug( evt ); } - INFO("P(x) = " << getValNoCache(evt) << " " << operator()(nullptr, evt.index() / utils::size::value ) ); + INFO("P(x) = " << getValNoCache(evt) << " " << operator()((const float_v*)nullptr, evt.index() / utils::size::value ) ); INFO("Prod = [" << vectorToString(m_pVector , ", ") <<"]"); } diff --git a/src/Projection.cpp b/src/Projection.cpp index 6d14b4b9a2f..0baec9f479c 100644 --- a/src/Projection.cpp +++ b/src/Projection.cpp @@ -45,6 +45,11 @@ TH1D* Projection::plot(const std::string& prefix) const { plot->GetYaxis()->SetTitleOffset(1.35); plot->SetMarkerSize(0); plot->SetMinimum(0); + + DEBUG("Returning plot: [" << m_min << " " << m_max << "] " << m_name << " " << + plot->GetXaxis()->GetBinLowEdge(1) << " " << + plot->GetXaxis()->GetBinLowEdge(1 + m_nBins) + ); return plot; } std::function Projection::binFunctor() const { @@ -73,7 +78,20 @@ std::pair Projection2D::operator()( const Event& evt ) const template <> TH1D* Projection::projInternal( const EventList& events, const ArgumentPack& args) const { - return events.makeProjection(*this, args); + auto selection = args.getArg().val; + auto weightFunction = args.getArg().val; + std::string prefix = args.getArg(std::string("")); + auto axis = plot(prefix); + axis->SetLineColor(args.getArg(kBlack).val); + axis->SetMarkerSize(0); + for( auto& evt : events ) + { + if( selection != nullptr && !selection(evt) ) continue; + auto pos = operator()(evt); + axis->Fill( pos, evt.weight() * ( weightFunction == nullptr ? 1 : weightFunction(evt) / evt.genPdf() ) ); + } + if( selection != nullptr ) INFO("Filter efficiency = " << axis->GetEntries() << " / " << events.size() ); + return axis; } template <> std::tuple, THStack*> Projection::projInternal(const EventList& events, const Projection::keyedFunctors& weightFunction, const ArgumentPack& args) const diff --git a/src/Spline.cpp b/src/Spline.cpp index c7c3de27547..bcdc41bf3ce 100644 --- a/src/Spline.cpp +++ b/src/Spline.cpp @@ -85,7 +85,7 @@ void SplineTransfer::print() const { INFO( "Source: " << m_parameters[0]->name() SplineTransfer::SplineTransfer() = default; SplineTransfer::SplineTransfer( const SplineTransfer& other ) - : CacheTransfer(other.m_address, other.m_value, other.m_size) + : CacheTransfer(other.m_address, other.m_name, other.m_value, other.m_size) , m_transferMatrix( other.m_transferMatrix ) , m_parameters( other.m_parameters ) , m_nKnots( other.m_nKnots ) @@ -94,8 +94,8 @@ SplineTransfer::SplineTransfer( const SplineTransfer& other ) { } -SplineTransfer::SplineTransfer( const size_t& address, const unsigned int& N, const double& min, const double& max ) - : CacheTransfer(address) +SplineTransfer::SplineTransfer( const size_t& address, const std::string& name, const unsigned int& N, const double& min, const double& max ) + : CacheTransfer(address, name) , m_transferMatrix( TMatrixD( N - 2, N - 2 ) ) , m_parameters( N, nullptr ) , m_nKnots(N) diff --git a/src/TreePhaseSpace.cpp b/src/TreePhaseSpace.cpp index 18ea846740a..d7cf82ec4f5 100644 --- a/src/TreePhaseSpace.cpp +++ b/src/TreePhaseSpace.cpp @@ -41,18 +41,22 @@ TreePhaseSpace::TreePhaseSpace(const std::vector& decayChains, const E m_top.push_back( Vertex::make(p) ); m_weights.push_back(1); } - setRandom(rndm); } - for( auto& w : m_weights ) w /= double(m_weights.size()); + setRandom(rndm); + double sum_of_weights = std::accumulate( m_weights.begin(), m_weights.end(), 0 ); + for( auto& w : m_weights ) w /= sum_of_weights; m_dice = std::discrete_distribution<>(m_weights.begin(), m_weights.end()); } Event TreePhaseSpace::makeEvent() { unsigned j = m_dice(m_gen); + // INFO("Producing event from tree: " << j ); + if( j >= m_top.size() ) ERROR("Out of bounds: " << j << " / " << m_top.size() ); m_top[j].generate(); auto event = m_top[j].event(m_type.size()); - event.setGenPdf(genPdf(event) / m_top[j].weight()); + double w = m_top[j].weight(); + event.setGenPdf( w == 0 ? 0 : genPdf(event) / w ); m_generatorRecord.push_back(j); return event; } @@ -87,56 +91,46 @@ double rho( const double& s, const double& s1, const double& s2) return sqrt( 1 - 2 * (s1+s2)/s + (s1-s2)*(s1-s2) /(s*s) ); } -TreePhaseSpace::Vertex::Vertex(const Particle& particle, const double& min) +TreePhaseSpace::Vertex::Vertex(const Particle& particle, const double& mass) : particle(particle) - , min(min) - , max(min) - , isStable(true) - , isBW(particle.lineshape() == "BW") + , min(mass) + , max(mass) + , type( Type::Stable ) , index(particle.index()) , bwMass(particle.props()->mass()) , bwWidth(particle.props()->width()) + , s(bwMass*bwMass) { if( index != 999 ) indices = {index}; - phiMin = atan((min*min - bwMass*bwMass)/(bwMass*bwWidth)); - phiMax = atan((min*min - bwMass*bwMass)/(bwMass*bwWidth)); -// if( isBW ) INFO( min << " ΔΦ= " << phiMax - phiMin << " " << bwMass << " " << bwWidth << " E= [" << max <<", " << min*min << "]" ); } -TreePhaseSpace::Vertex::Vertex(const Particle& particle, const double& min, const double& max, const bool& isStable ) +TreePhaseSpace::Vertex::Vertex(const Particle& particle, const double& min, const double& max ) : particle(particle) - , min(min) - , max(max) - , isStable(isStable) - , isBW(particle.lineshape() == "BW") , index(particle.index()) , bwMass(particle.props()->mass()) , bwWidth(particle.props()->width()) + , min(min) + , max(max) + , s(bwMass*bwMass) { + if( particle.isStable() ) type = Type::Stable; + else if( particle.isQuasiStable() ) type = Type::QuasiStable; + else if( particle.lineshape().find("BW") != std::string::npos ){ + type = Type::BW; + phiMin = atan((min*min - bwMass*bwMass)/(bwMass*bwWidth)); + phiMax = atan((max*max - bwMass*bwMass)/(bwMass*bwWidth)); + INFO( particle << " [" << min << ", " << max << "] Φ = " << phiMin << ", " << phiMax ); + } + else type = Type::Flat; if( index != 999 ) indices = {index}; - phiMin = atan((min*min - bwMass*bwMass)/(bwMass*bwWidth)); - phiMax = atan((max*max - bwMass*bwMass)/(bwMass*bwWidth)); } double TreePhaseSpace::Vertex::p() const { return 0.5 * sqrt( s - 2 * (left->s+right->s) + (left->s-right->s)*(left->s-right->s)/s ); } - -double TreePhaseSpace::Vertex::genBW() const -{ - return isBW ? bwMass * bwMass + bwMass * bwWidth * tan( ( phiMax - phiMin ) * rand->Rndm() + phiMin ) : (max*max-min*min)*rand->Rndm() + min*min; -} - -double TreePhaseSpace::Vertex::BW(const double& si) const -{ - double m = bwMass; - double w = bwWidth; - double N = m * w / (phiMax - phiMin); - return isBW ? N / ( (si - m*m)*(si-m*m) + m*m*w*w) : 1./(max*max - min*min); -} - + double TreePhaseSpace::Vertex::weight() const { if( left == nullptr || right == nullptr ) return 1.0; @@ -148,37 +142,44 @@ double TreePhaseSpace::Vertex::weight() const return w; } -double TreePhaseSpace::Vertex::maxWeight() const -{ - double w = 1.0; - if( left == nullptr || right == nullptr ) return 1.0; - w *= rhoMax; - w *= left -> maxWeight(); - w *= right -> maxWeight(); - return w; -} - double TreePhaseSpace::Vertex::genPdf(const Event& event) const { if( left == nullptr || right == nullptr ) return 1; - double dp = left->genPdf(event) * right->genPdf(event); - return dp * ( isStable ? 1 : BW( event.s(indices) ) ); + double dp = left->genPdf(event) * right->genPdf(event); + auto st = event.s(indices); + switch( type ) { + case Type::BW : + dp *= ( bwMass* bwWidth ) /( (phiMax-phiMin) * ( (st - bwMass*bwMass)*(st-bwMass*bwMass) + bwMass*bwMass*bwWidth*bwWidth) ); + break; + case Type::Flat : + dp *= 1/(max*max -min*min); + break; + }; + return dp; } void TreePhaseSpace::Vertex::generate() { - s = isStable ? min*min : genBW(); + switch( type ) { + case Type::BW : + s = bwMass * bwMass + bwMass * bwWidth * tan( (phiMax - phiMin ) * rand->Rndm() + phiMin ); + break; + case Type::Flat : + s = (max*max-min*min)*rand->Rndm() + min; + break; + }; if( left != nullptr ) left->generate(); if( right != nullptr ) right->generate(); } void TreePhaseSpace::Vertex::print(const unsigned& offset) const { - double rhoc = ( left != nullptr && right != nullptr ? rho(s,left->s,right->s) : rhoMax ); - if( isStable ) - INFO( std::string(offset,' ') << particle.name() << " [" << vectorToString(indices, ", ") << "] → [" << min << "], ϱ' = " << rhoMax << ", s = " << s << ", ϱ = " << rhoc << " w = " << maxWeight() ); - else - INFO( std::string(offset,' ') << particle.name() << " [" << vectorToString(indices, ", ") << "] → [" << min << ", " << max << "] ϱ' =" << rhoMax << ", s = " << s << ", ϱ = " << rhoc << " w = " << maxWeight() ); + std::array vtxTypeStrings = {"BW", "Flat", "Stable", "QuasiStable"}; + INFO( std::string(offset,' ') << particle.name() << " [" << vectorToString(indices, ", ") << "] type = " << vtxTypeStrings[ type ] << " → [" << min << ", " << max << "] " << sqrt(s) ); + if( type == Type::BW ) + INFO( "phi-range : " << phiMin << " " << phiMax + << " s(min) = " << bwMass * bwMass + bwMass * bwWidth * tan(phiMin) + << " s(max) = " << bwMass * bwMass + bwMass * bwWidth * tan(phiMax) ); if( left != nullptr ) left -> print( offset + 4 ); if( right != nullptr ) right -> print( offset + 4 ); } @@ -197,6 +198,7 @@ void TreePhaseSpace::Vertex::place(Event& event) Event TreePhaseSpace::Vertex::event(const unsigned& eventSize) { + if( isMultiBody ) return phsp.makeEvent(); Event output(4 * eventSize); mom.SetXYZT(0,0,0,sqrt(s)); generateFullEvent(); @@ -213,6 +215,10 @@ void TreePhaseSpace::Vertex::generateFullEvent() double cosPhi = cos(angY); double sinPhi = sin(angY); double pf = p(); + if( std::isnan(pf) || std::isnan(s) ) + { + ERROR("Generating nan: " << pf << " " << s << " " << min << " " << max ); + } left -> mom.SetXYZT( pf*sinTheta*cosPhi, pf*sinTheta*sinPhi, pf*cosTheta, sqrt(left->s + pf*pf) ); left -> mom.Boost( mom.BoostVector() ); left -> generateFullEvent(); @@ -222,12 +228,6 @@ void TreePhaseSpace::Vertex::generateFullEvent() right -> generateFullEvent(); } -void TreePhaseSpace::Vertex::setRhoMax() -{ - rhoMax = rho(max*max, left->min * left->min, right->min * right->min ); - weightMax = maxWeight(); -} - TreePhaseSpace::Vertex TreePhaseSpace::Vertex::make(const Particle& particle, TreePhaseSpace::Vertex* parent) { auto decayProducts = particle.daughters(); @@ -241,25 +241,17 @@ TreePhaseSpace::Vertex TreePhaseSpace::Vertex::make(const Particle& particle, Tr if( decayProducts.size() == 2 ) { double G = particle.isQuasiStable() ? 0 : particle.props()->width() * 10; - TreePhaseSpace::Vertex vtx = (parent == nullptr) ? TreePhaseSpace::Vertex(particle, particle.mass() - G , particle.mass() + G, particle.isQuasiStable() ) : TreePhaseSpace::Vertex(); + TreePhaseSpace::Vertex vtx = (parent == nullptr) ? TreePhaseSpace::Vertex(particle, particle.mass() - G , particle.mass() + G) : TreePhaseSpace::Vertex(); parent = ( parent == nullptr ) ? &vtx : parent; - auto min_mass_1 = threshold(*decayProducts[0]); auto min_mass_2 = threshold(*decayProducts[1]); - auto max_mass_1 = decayProducts[0]->isStable() ? min_mass_1 : parent->max - min_mass_2; - auto max_mass_2 = decayProducts[1]->isStable() ? min_mass_2 : parent->max - min_mass_1; - parent->left = std::make_shared(*decayProducts[0], min_mass_1, max_mass_1, decayProducts[0]->isStable() ); - parent->right = std::make_shared(*decayProducts[1], min_mass_2, max_mass_2, decayProducts[1]->isStable() ); + parent->left = std::make_shared(*decayProducts[0], min_mass_1, parent->max - min_mass_2); + parent->right = std::make_shared(*decayProducts[1], min_mass_2, parent->max - min_mass_1); TreePhaseSpace::Vertex::make(*decayProducts[0], parent->left.get()); TreePhaseSpace::Vertex::make(*decayProducts[1], parent->right.get()); for( auto& index : parent->left ->indices ) parent->indices.push_back(index); for( auto& index : parent->right->indices ) parent->indices.push_back(index); - parent->setRhoMax(); - return *parent; - } - if( decayProducts.size() > 2 ) - { - ERROR("Decomposition only implemented for quasi two-body decays, vertex: " << particle << " does not result in valid phase space"); + return *parent; } return TreePhaseSpace::Vertex(); } @@ -286,7 +278,7 @@ double TreePhaseSpace::genPdf(const Event& event) const { double genPdf = 0; for( unsigned i = 0; i != m_top.size(); ++i ) - genPdf += m_weights[i] * m_top[i].genPdf(event); // / channel.weightMax; // / channel->w; + genPdf += m_weights[i] * m_top[i].genPdf(event); return genPdf; } diff --git a/src/Units.cpp b/src/Units.cpp index 9ae73ad916d..a252032892c 100644 --- a/src/Units.cpp +++ b/src/Units.cpp @@ -3,11 +3,11 @@ #include "AmpGen/Utilities.h" namespace AmpGen { - complete_enum(Units, TeV, GeV, MeV, KeV, eV) + complete_enum(Units, TeV, GeV, MeV, KeV, eV, ms, us, ns, ps, fs) } double AmpGen::to_double(const AmpGen::Units& unit) { - static const double value_table[5] = {TeV, GeV, MeV, KeV, eV}; + static const double value_table[10] = {TeV, GeV, MeV, KeV, eV, ms, us, ns, ps, fs}; return value_table[unsigned(unit)]; } diff --git a/test/test_avx2d.cpp b/test/test_avx2d.cpp index d1ce7d48435..965b8426abd 100644 --- a/test/test_avx2d.cpp +++ b/test/test_avx2d.cpp @@ -7,7 +7,7 @@ namespace utf = boost::unit_test; -#if ENABLE_AVX2 +#if ENABLE_AVX #include "AmpGen/simd/utils.h" using namespace AmpGen; @@ -17,10 +17,10 @@ BOOST_AUTO_TEST_CASE( test_log ) { AVX2d::real_v p(0.3, 0.5, 10.0, 7.0); auto logged = AVX2d::log( p ).to_array() ; - BOOST_TEST( logged[0] == std::log(0.3), boost::test_tools::tolerance(5e-10 ) ); - BOOST_TEST( logged[1] == std::log(0.5), boost::test_tools::tolerance(5e-10 ) ); - BOOST_TEST( logged[2] == std::log(10.0), boost::test_tools::tolerance(5e-10 ) ); - BOOST_TEST( logged[3] == std::log(7.0), boost::test_tools::tolerance(5e-10 ) ); + BOOST_TEST( logged[0] == std::log(0.3), boost::test_tools::tolerance(1e-12 ) ); + BOOST_TEST( logged[1] == std::log(0.5), boost::test_tools::tolerance(1e-12 ) ); + BOOST_TEST( logged[2] == std::log(10.0), boost::test_tools::tolerance(1e-12 ) ); + BOOST_TEST( logged[3] == std::log(7.0), boost::test_tools::tolerance(1e-12 ) ); } BOOST_AUTO_TEST_CASE( test_fmod ) @@ -65,6 +65,29 @@ BOOST_AUTO_TEST_CASE( test_gather ) BOOST_TEST( v[3] == data[4] ); } +BOOST_AUTO_TEST_CASE( test_trig ) +{ + auto data = AVX2d::real_v(0.1,0.4,-2.0,5.0); + auto cos = AVX2d::cos(data).to_array(); + BOOST_TEST( cos[0] == std::cos( data.at(0 )) , boost::test_tools::tolerance(1e-15) ); + BOOST_TEST( cos[1] == std::cos( data.at(1 )) , boost::test_tools::tolerance(1e-15) ); + BOOST_TEST( cos[2] == std::cos( data.at(2)) , boost::test_tools::tolerance(1e-15) ); + BOOST_TEST( cos[3] == std::cos( data.at(3 )) , boost::test_tools::tolerance(1e-15) ); + + auto sin = AVX2d::sin(data).to_array(); + BOOST_TEST( sin[0] == std::sin( data.at(0 )) , boost::test_tools::tolerance(1e-15) ); + BOOST_TEST( sin[1] == std::sin( data.at(1 )) , boost::test_tools::tolerance(1e-15) ); + BOOST_TEST( sin[2] == std::sin( data.at(2)) , boost::test_tools::tolerance(1e-15) ); + BOOST_TEST( sin[3] == std::sin( data.at(3 )) , boost::test_tools::tolerance(1e-15) ); + + auto tan = AVX2d::tan(data).to_array(); + + BOOST_TEST( tan[0] == std::tan( data.at(0 )) , boost::test_tools::tolerance(1e-15) ); + BOOST_TEST( tan[1] == std::tan( data.at(1 )) , boost::test_tools::tolerance(1e-15) ); + BOOST_TEST( tan[2] == std::tan( data.at(2)) , boost::test_tools::tolerance(1e-15) ); + BOOST_TEST( tan[3] == std::tan( data.at(3 )) , boost::test_tools::tolerance(1e-15) ); +} + #else BOOST_AUTO_TEST_CASE( test_dummy ) From fb6a9a0599657f4f3ab4c9acd5e0ca16668bf977 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sat, 16 May 2020 14:24:55 +0200 Subject: [PATCH 199/250] Fix OpenMP predicates --- AmpGen/Generator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AmpGen/Generator.h b/AmpGen/Generator.h index 4ab6e0676a1..b864c166d1e 100644 --- a/AmpGen/Generator.h +++ b/AmpGen/Generator.h @@ -99,7 +99,7 @@ namespace AmpGen #ifdef _OPENMP #pragma omp parallel for #endif - for ( size_t block=0; block != mc.nBlocks(); ++block ) + for ( size_t block=0; block < mc.nBlocks(); ++block ) mc.setWeight(block, 1.0, pdf(mc.block(block), block) / mc.genPDF(block)); t_eval.stop(); t_acceptReject.start(); From 958c379d882db03e7ed7e8694b8508904ffa1969 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 17 May 2020 11:31:40 +0200 Subject: [PATCH 200/250] Options to switch of mvec --- AmpGen/simd/avx2d_types.h | 41 ++++++++++++++++++++++++++------------- Standalone.cmake | 20 ++++++++++++++++--- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/AmpGen/simd/avx2d_types.h b/AmpGen/simd/avx2d_types.h index 88ab0bfdd4b..bdd949c88bc 100644 --- a/AmpGen/simd/avx2d_types.h +++ b/AmpGen/simd/avx2d_types.h @@ -8,18 +8,24 @@ #include #include +#if USE_MVEC extern "C" __m256d _ZGVcN4v_cos(__m256d x); extern "C" __m256d _ZGVcN4v_sin(__m256d x); extern "C" __m256d _ZGVcN4v_exp(__m256d x); extern "C" __m256d _ZGVcN4v_log(__m256d x); extern "C" void _ZGVdN4vvv_sincos(__m256d x, __m256i ptrs, __m256i ptrc); +#endif namespace AmpGen { namespace AVX2d { - - #define libmvec_alias( function_name, avx_function_name ) \ - inline real_v function_name( const real_v& v ){ return avx_function_name (v) ; } - + #if USE_MVEC + #define libmvec_alias( function_name) \ + inline real_v function_name( const real_v& v ){ return _ZGVcN4v_##function_name (v) ; } + #else + #define libmvec_alias( F ) \ + inline real_v F( const real_v& v ){ auto arr = v.to_array(); return real_v( std::F(arr[0]), std::F(arr[1]), std::F(arr[2]), std::F(arr[3])) ; } + #endif + struct real_v { __m256d data; static constexpr unsigned size = 4; @@ -29,8 +35,7 @@ namespace AmpGen { real_v(const double& f ) : data( _mm256_set1_pd( f )) {} real_v(const double& x0, const double& x1, const double& x2, const double& x3 ) { - double tmp[4] = {x0,x1,x2,x3}; - data = _mm256_loadu_pd(tmp); + data = _mm256_set_pd(x0,x1,x2,x3); } real_v(const double* f ) : data( _mm256_loadu_pd( f ) ) {} real_v(const std::array f ) : data( _mm256_loadu_pd( f.data() ) ) {} @@ -60,22 +65,30 @@ namespace AmpGen { inline real_v operator==( const real_v& lhs, const real_v& rhs ){ return _mm256_cmp_pd( lhs, rhs, _CMP_EQ_OS ); } inline real_v sqrt( const real_v& v ) { return _mm256_sqrt_pd(v); } inline real_v abs ( const real_v& v ) { return _mm256_andnot_pd(_mm256_set1_pd(-0.), v); } - - libmvec_alias( sin, _ZGVcN4v_sin ) - libmvec_alias( cos, _ZGVcN4v_cos ) - libmvec_alias( exp, _ZGVcN4v_exp ) - libmvec_alias( log, _ZGVcN4v_log ) + libmvec_alias( sin ) + libmvec_alias( cos ) + libmvec_alias( exp ) + libmvec_alias( log ) inline void sincos( const real_v& v, real_v& s, real_v& c ) { +#if USE_MVEC __m256i sp = _mm256_add_epi64(_mm256_set1_epi64x((uint64_t)&s),_mm256_set_epi64x(24,16,8,0)); __m256i cp = _mm256_add_epi64(_mm256_set1_epi64x((uint64_t)&c),_mm256_set_epi64x(24,16,8,0)); _ZGVdN4vvv_sincos(v,sp,cp); +#else + s = sin(v); + c = cos(v); +#endif + } + inline std::pair sincos( const real_v& v ) + { + std::pair rt; + sincos( v, rt.first, rt.second ); + return rt; } - inline real_v tan( const real_v& v ) { - real_v s, c; - sincos( v, s, c ); + auto [s,c] = sincos( v ); return s / c ; } diff --git a/Standalone.cmake b/Standalone.cmake index a476fb87bd9..c2284d0e92e 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -12,8 +12,9 @@ if( NOT "${CMAKE_CXX_STANDARD}" ) set(CMAKE_CXX_STANDARD 17) endif() -SET(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") -SET(USE_SIMD "AVX2d" CACHE STRING "USE_SIMD") +SET(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") # flag to use openmp for threading +SET(USE_SIMD "AVX2d" CACHE STRING "USE_SIMD") # AVX instruction set + precision to use +SET(USE_MVEC TRUE CACHE BOOL "USE_MVEC") # flag to use vector math library mvec set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -31,6 +32,7 @@ include(GNUInstallDirs) option(AMPGEN_DEBUG "AmpGen Debug printout") option(AMPGEN_TRACE "AmpGen Trace printout") + configure_file ("${PROJECT_SOURCE_DIR}/AmpGen/Version.h.in" "${CMAKE_BINARY_DIR}/AmpGenVersion.h") add_library(${PROJECT_NAME} SHARED ${AMPGEN_SRC} ${AMPGEN_HDR}) @@ -64,7 +66,19 @@ target_include_directories(AmpGen PUBLIC $ Date: Sun, 17 May 2020 11:58:31 +0200 Subject: [PATCH 201/250] cleanup mvec code --- AmpGen/simd/avx2d_types.h | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/AmpGen/simd/avx2d_types.h b/AmpGen/simd/avx2d_types.h index bdd949c88bc..7293f30118d 100644 --- a/AmpGen/simd/avx2d_types.h +++ b/AmpGen/simd/avx2d_types.h @@ -9,22 +9,24 @@ #include #if USE_MVEC -extern "C" __m256d _ZGVcN4v_cos(__m256d x); -extern "C" __m256d _ZGVcN4v_sin(__m256d x); -extern "C" __m256d _ZGVcN4v_exp(__m256d x); -extern "C" __m256d _ZGVcN4v_log(__m256d x); +// extern "C" __m256d _ZGVcN4v_cos(__m256d x); +// extern "C" __m256d _ZGVcN4v_sin(__m256d x); +// extern "C" __m256d _ZGVcN4v_exp(__m256d x); +// extern "C" __m256d _ZGVcN4v_log(__m256d x); extern "C" void _ZGVdN4vvv_sincos(__m256d x, __m256i ptrs, __m256i ptrc); #endif +#if USE_MVEC +#define libmvec_alias( function_name) \ + extern "C" __m256d _ZGVcN4v_##function_name(__m256d x); \ + inline real_v function_name( const real_v& v ){ return _ZGVcN4v_##function_name (v) ; } +#else +#define libmvec_alias( F ) \ + inline real_v F( const real_v& v ){ auto arr = v.to_array(); return real_v( std::F(arr[0]), std::F(arr[1]), std::F(arr[2]), std::F(arr[3])) ; } +#endif + namespace AmpGen { namespace AVX2d { - #if USE_MVEC - #define libmvec_alias( function_name) \ - inline real_v function_name( const real_v& v ){ return _ZGVcN4v_##function_name (v) ; } - #else - #define libmvec_alias( F ) \ - inline real_v F( const real_v& v ){ auto arr = v.to_array(); return real_v( std::F(arr[0]), std::F(arr[1]), std::F(arr[2]), std::F(arr[3])) ; } - #endif struct real_v { __m256d data; From 064296da3bbf14d12e9cdc87c4ef83d559fa742f Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 17 May 2020 15:27:09 +0200 Subject: [PATCH 202/250] fix scalar build --- AmpGen/AmplitudeRules.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/AmpGen/AmplitudeRules.h b/AmpGen/AmplitudeRules.h index ed44420896f..57e30519d34 100644 --- a/AmpGen/AmplitudeRules.h +++ b/AmpGen/AmplitudeRules.h @@ -187,7 +187,9 @@ namespace AmpGen } template auto operator()(arg_types... args ) const { return amp_type::operator()(args...) ; } #if ENABLE_AVX - void debug( const Event& event ) const { amp_type::debug(EventListSIMD::makeEvent(event).data() ) ; } + void debug( const Event& event ) const { amp_type::debug(EventListSIMD::makeEvent(event).data() ) ; } + #else + void debug( const Event& event ) const { amp_type::debug(event.address()) ; } #endif const std::string decayDescriptor() const { return decayTree.decayDescriptor() ; } From 0ddc4eb3f8bc6d70aff707165dd8d440c8d34871 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 19 May 2020 18:15:10 +0200 Subject: [PATCH 203/250] Fixes for canonical formulation with deeper decay topologies --- AmpGen/ASTResolver.h | 3 +- AmpGen/Expression.h | 1 + AmpGen/Projection.h | 2 +- AmpGen/Transform.h | 16 +++-- AmpGen/Wigner.h | 10 +++- CMakeLists.txt | 4 +- apps/Debugger.cpp | 3 + apps/Generator.cpp | 1 + examples/FitterWithPolarisation.cpp | 10 +++- src/ASTResolver.cpp | 32 ++++++---- src/EventType.cpp | 2 +- src/Expression.cpp | 4 +- src/OptionsParser.cpp | 3 + src/Particle.cpp | 6 +- src/PolarisedSum.cpp | 2 +- src/RecursivePhaseSpace.cpp | 2 +- src/Transform.cpp | 90 +++++++++++++++++++++-------- src/Wigner.cpp | 57 ++++++++++++------ 18 files changed, 173 insertions(+), 75 deletions(-) diff --git a/AmpGen/ASTResolver.h b/AmpGen/ASTResolver.h index bbad189fb1c..1a29a215a47 100644 --- a/AmpGen/ASTResolver.h +++ b/AmpGen/ASTResolver.h @@ -60,11 +60,12 @@ namespace AmpGen { std::map m_evtMap; /// Event specification std::map m_parameterMapping; /// Mapping of parameters to compile parameters const MinuitParameterSet* m_mps; /// Set of MinuitParameters - std::map m_tempTrees; /// temporary store of sub-trees for performing cse reduction + std::map m_tempTrees; /// temporary store of sub-trees for performing cse reduction unsigned int m_nParameters; /// Number of parameters bool m_enable_cuda {false}; /// flag to generate CUDA code <> bool m_enable_compileTimeConstants {false}; /// flag to enable compile time constants <> bool m_enable_avx {false}; /// flag to generate code using AVX instructions <> + bool m_check_hashes {false}; /// flag to check that hashes are unique }; template <> void ASTResolver::resolve( const Parameter& obj ); diff --git a/AmpGen/Expression.h b/AmpGen/Expression.h index 49fe25acc3f..d40596edf48 100644 --- a/AmpGen/Expression.h +++ b/AmpGen/Expression.h @@ -233,6 +233,7 @@ namespace AmpGen complex_t operator()() const override { return m_expression(); } uint64_t key() const; void setKey( const size_t& new_key ); + Expression expression() const { return m_expression; } Expression m_expression; uint64_t m_key; }; diff --git a/AmpGen/Projection.h b/AmpGen/Projection.h index ce6c926ea53..8192ef58c25 100644 --- a/AmpGen/Projection.h +++ b/AmpGen/Projection.h @@ -56,7 +56,7 @@ namespace AmpGen } friend class Projection2D; - private: + /// private: template TH1D* projInternal(const eventlist_type&, const ArgumentPack&) const; template diff --git a/AmpGen/Transform.h b/AmpGen/Transform.h index 0bf87a5edfb..1c703a7b056 100644 --- a/AmpGen/Transform.h +++ b/AmpGen/Transform.h @@ -41,13 +41,16 @@ namespace AmpGen { class TransformSequence { public: - TransformSequence() = default; + TransformSequence(); + TransformSequence( const Transform& transform ); + TransformSequence( const TransformSequence& t1, const TransformSequence& t2); + TransformSequence( const Transform& t1, const Transform& t2); TransformSequence inverse() const; - Tensor operator()( const Transform::Representation& repr ); + Tensor operator()( const Transform::Representation& repr ) const ; Tensor operator()( const Tensor& tensor, - const Transform::Representation& repr=Transform::Representation::Vector ); - void add( const Transform& transform ); - void add( const TransformSequence& transform ); + const Transform::Representation& repr=Transform::Representation::Vector ) const; + void push_back( const Transform& transform ); + void push_back( const TransformSequence& transform ); void stepThrough( const Tensor& tensor, const Transform::Representation& repr = Transform::Representation::Vector ); @@ -58,7 +61,10 @@ namespace AmpGen { std::vector::const_iterator end() const { return m_transforms.cend(); } std::vector::iterator begin() { return m_transforms.begin(); } std::vector::iterator end() { return m_transforms.end(); } + unsigned size() const { return m_transforms.size(); } + private: + void buildCache(); std::vector m_transforms; std::array m_cache; }; diff --git a/AmpGen/Wigner.h b/AmpGen/Wigner.h index 9abdcf1f372..01a3792ec63 100644 --- a/AmpGen/Wigner.h +++ b/AmpGen/Wigner.h @@ -7,6 +7,7 @@ namespace AmpGen { class Particle; + using TransformCache = std::map; Expression wigner_d( const Expression& cb, const double& j, const double& m, const double& n ); Expression wigner_D( const std::pair& P, const double& J, const double& lA, const double& lB, DebugSymbols* db); @@ -27,9 +28,14 @@ namespace AmpGen { In the case where ve =-1, a second rotation is applied about the x-axis that aligns P to the +ve z-axis. This ensures that singly and doubly primed helicity frames remain orthonormal. */ - TransformSequence wickTransform(const Tensor& P, const Expression& M, const int& ve =1, const bool& handleZeroCase = false); + TransformSequence wickTransform(const Tensor& P, const Particle& p, const int& ve =1, DebugSymbols* db = nullptr ); - Expression helicityAmplitude(const Particle& particle, TransformSequence& parentFrame, const double& Mz, DebugSymbols* db , const int sgn=1, std::map* cacheptr = nullptr); + Expression helicityAmplitude(const Particle& particle, + const TransformSequence& parentFrame, + const double& Mz, + DebugSymbols* db , + const int sgn=1, + TransformCache* cacheptr = nullptr); Tensor basisSpinor(const int& polState, const int& id); Tensor basisVector(const int& polState); diff --git a/CMakeLists.txt b/CMakeLists.txt index 04680a05846..ad75fc9b283 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ # Support standalone build if(COMMAND gaudi_subdir) - gaudi_subdir(AmpGen v1r2) + gaudi_subdir(AmpGen v2r0) find_package(ROOT COMPONENTS RIO Hist Matrix Graf Minuit2 Tree MathMore MathCore Physics) find_package(TBB REQUIRED) @@ -29,6 +29,6 @@ if(COMMAND gaudi_subdir) endforeach() else() cmake_minimum_required(VERSION 3.12) - project(AmpGen LANGUAGES CXX VERSION 1.2) + project(AmpGen LANGUAGES CXX VERSION 2.0) include(Standalone.cmake) endif() diff --git a/apps/Debugger.cpp b/apps/Debugger.cpp index a19f3f83563..98308235d4a 100644 --- a/apps/Debugger.cpp +++ b/apps/Debugger.cpp @@ -98,6 +98,9 @@ int main( int argc, char** argv ) accepted.push_back(evt); } } + std::vector event = NamedParameter("Event",0).getVector(); + if( event.size() != 1 ) accepted[0].set( event.data() ); + std::string type = NamedParameter("Type","CoherentSum"); if( type == "PolarisedSum") diff --git a/apps/Generator.cpp b/apps/Generator.cpp index a8f77720b72..00ea2e10643 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -153,6 +153,7 @@ int main( int argc, char** argv ) omp_set_dynamic( 0 ); #endif + INFO("Writing output: " << outfile ); TRandom3 rand; rand.SetSeed( seed + 934534 ); diff --git a/examples/FitterWithPolarisation.cpp b/examples/FitterWithPolarisation.cpp index 79620f5d706..bc36c2ac700 100644 --- a/examples/FitterWithPolarisation.cpp +++ b/examples/FitterWithPolarisation.cpp @@ -9,6 +9,7 @@ #include #include "AmpGen/Chi2Estimator.h" +#include "AmpGen/RecursivePhaseSpace.h" #include "AmpGen/EventList.h" #include "AmpGen/EventType.h" #include "AmpGen/CoherentSum.h" @@ -42,6 +43,11 @@ using namespace AmpGen; +template Particle getTopology(const pdf_t& pdf) +{ + return pdf.matrixElements()[0].decayTree.quasiStableTree(); +} + template FitResult* doFit( PDF&& pdf, EventList_type& data, EventList_type& mc, MinuitParameterSet& MPS ); @@ -108,7 +114,9 @@ int main( int argc, char* argv[] ) /* Generate events to normalise the PDF with. This can also be loaded from a file, which will be the case when efficiency variations are included. Default number of normalisation events is 2 million. */ - EventList_type eventsMC = simFile == "" ? EventList_type(Generator<>(evtType, &rndm).generate(int(3365617)) ) : EventList_type(simFile, evtType); + Generator signalGenerator( getTopology(sig), events.eventType(), &rndm ); + auto events_l = signalGenerator.generate(1e6); + EventList_type eventsMC = simFile == "" ? EventList_type(events_l) : EventList_type(simFile, evtType); sig.setMC( eventsMC ); diff --git a/src/ASTResolver.cpp b/src/ASTResolver.cpp index 6118fb62795..3b2b5bfe0b7 100644 --- a/src/ASTResolver.cpp +++ b/src/ASTResolver.cpp @@ -20,6 +20,7 @@ ASTResolver::ASTResolver(const std::map& evtMap, { m_enable_cuda = NamedParameter("UseCUDA",false); m_enable_compileTimeConstants = NamedParameter("ASTResolver::CompileTimeConstants", false); + m_check_hashes = NamedParameter("ASTResolver::CheckHashes", false ); } std::vector> ASTResolver::getOrderedSubExpressions( const Expression& expression ) @@ -30,19 +31,22 @@ std::vector> ASTResolver::getOrderedSubExpression std::map subTrees; do { subTrees.clear(); - for( auto& t : m_tempTrees ) + for( auto& [t, s] : m_tempTrees ) { - auto expr = t.first->m_expression; - uint64_t key = t.first->key(); - if( subTrees.count( key ) == 0 ) subTrees[ key ] = t.first->m_expression ; + uint64_t key = s->key(); + if( subTrees.count( key ) == 0 ) subTrees[ key ] = s->expression(); + // else if( m_check_hashes && t.first->m_expression.to_string() != subTrees[key].to_string() ) + // { + // WARNING("Hash collision between in key = " << key << " other key = " << FNV1a_hash( subTrees[key].to_string() ) ); + // } } m_tempTrees.clear(); - for( auto& st : subTrees ){ - st.second.resolve( *this ); - auto stack_pos = used_functions.find( st.first ); + for( auto& [key,expression] : subTrees ){ + expression.resolve( *this ); + auto stack_pos = used_functions.find(key); if ( stack_pos == used_functions.end() ) { - subexpressions.emplace_back( st.first , st.second ); - used_functions[st.first] = subexpressions.size() - 1; + subexpressions.emplace_back(key , expression ); + used_functions[key] = subexpressions.size() - 1; continue; } auto oldPos = stack_pos->second; @@ -52,7 +56,7 @@ std::vector> ASTResolver::getOrderedSubExpression for ( auto uf = used_functions.begin(); uf != used_functions.end(); ++uf ) { if ( uf->second >= oldPos ) uf->second = uf->second - 1; } - used_functions[st.first] = subexpressions.size() - 1; + used_functions[key] = subexpressions.size() - 1; } } while ( subTrees.size() !=0 ); std::reverse( subexpressions.begin(), subexpressions.end() ); @@ -61,8 +65,12 @@ std::vector> ASTResolver::getOrderedSubExpression template <> void ASTResolver::resolve( const SubTree& subTree ) { - if( m_tempTrees.count( &subTree ) != 0 ) return; - m_tempTrees[&subTree] = 1; + auto ptr = subTree.expression().get(); + if( m_tempTrees.count(ptr) != 0 ) return; + else { + ptr->resolve( *this ); + m_tempTrees[ptr] = &subTree; + } } template <> void ASTResolver::resolve( const Spline& spline ) diff --git a/src/EventType.cpp b/src/EventType.cpp index 1bace03da37..c111e0ced4d 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -54,7 +54,7 @@ EventType::EventType( const std::vector& particleNames, const bool& if ( prop != nullptr ) m_particleMasses.push_back( prop->mass() ); else { - ERROR( "Particle not found: " << *m_particleNames.rbegin() ); + FATAL( "Particle not found: " << *m_particleNames.rbegin() ); return; } if(m_alt_part_names) diff --git a/src/Expression.cpp b/src/Expression.cpp index f0ec105523c..64661e26c85 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -157,7 +157,7 @@ Expression AmpGen::operator/( const Expression& A, const Expression& B ) if( is( as_prod.r() ) ) return ( Constant( 1./as_prod.r()() ) * A )/ as_prod.l(); } else if( is(B) ) return ( A * cast(B).r() ) / cast(B).l(); - else if( is(B) ) return ( A * fcn::isqrt( cast(B).arg() ) ); +// else if( is(B) ) return ( A / fcn::sqrt( cast(B).arg() ) ); return Expression( Divide( A, B ) ); } Expression AmpGen::operator&&( const Expression& A, const Expression& B ) { return Expression( And( A, B ) ); } @@ -249,7 +249,7 @@ std::string SubTree::to_string(const ASTResolver* /*resolver*/) const void SubTree::resolve( ASTResolver& resolver ) const { resolver.resolve( *this ); - m_expression.resolve( resolver ); + // m_expression.resolve( resolver ); } Expression AmpGen::make_cse( const Expression& A , bool simplify ) diff --git a/src/OptionsParser.cpp b/src/OptionsParser.cpp index 74cfab93f20..469794aed18 100644 --- a/src/OptionsParser.cpp +++ b/src/OptionsParser.cpp @@ -110,6 +110,9 @@ void OptionsParser::addArg( const std::string& arg ) int bc = 0 ; auto tokens = makeParsedStrings( arg, bc ); auto name = tokens[0]; + if ( name == "ParticlePropertiesList::Alias" && tokens.size() == 3 ) { + ParticlePropertiesList::getMutable()->makeAlias( tokens[1], tokens[2] ); + } m_parsedLines[name] = tokens; } diff --git a/src/Particle.cpp b/src/Particle.cpp index caa73e54681..35d2ac2e2a7 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -194,9 +194,9 @@ Tensor Particle::P() const Tensor rt( std::vector( { Parameter(index + "_Px"), Parameter(index + "_Py"), - Parameter(index + "_Pz"), 0 }) , Tensor::dim(4) ); - rt[3] = make_cse( fcn::sqrt( mass()*mass() + rt[0]*rt[0] + rt[1]*rt[1] + rt[2]*rt[2] ) ); - // Parameter( index + "_E" , 0, false, 1 )} ), + Parameter(index + "_Pz"), + Parameter(index + "_E") }) , Tensor::dim(4) ); +// rt[3] = fcn::sqrt( mass()*mass() + rt[0]*rt[0] + rt[1]*rt[1] + rt[2]*rt[2] ) ; return rt; } else ERROR( "Stable particle " << m_index << "is unindexed!" ); } diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 3796544f40b..0684979664a 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -69,7 +69,7 @@ PolarisedSum::PolarisedSum(const EventType& type, auto protoAmps = m_rules.getMatchingRules(m_eventType); for(const auto& m : protoAmps ) INFO( m.first.uniqueString() ); m_matrixElements.resize( protoAmps.size() ); - ThreadPool tp( std::thread::hardware_concurrency() ); + ThreadPool tp(std::thread::hardware_concurrency() ); for(unsigned i = 0; i < m_matrixElements.size(); ++i) { tp.enqueue( [i, &protoAmps, &polStates, this]{ diff --git a/src/RecursivePhaseSpace.cpp b/src/RecursivePhaseSpace.cpp index c8f67908071..dad48e3fbde 100644 --- a/src/RecursivePhaseSpace.cpp +++ b/src/RecursivePhaseSpace.cpp @@ -58,7 +58,7 @@ AmpGen::Event RecursivePhaseSpace::makeEvent() rt[4*segment.sink + 3] = pE; } } else { - auto evtTmp = segment.decayProds->makeEvent(); + auto evtTmp = segment.decayProds->makeEvent(); double v = sqrt( px * px + py * py + pz * pz ) / pE; boost( evtTmp, std::tuple(px, py, pz), v ); for(size_t j = 0; j < rt.size(); ++j) rt[j] += evtTmp[j]; diff --git a/src/Transform.cpp b/src/Transform.cpp index cd504e38634..812a6bef05e 100644 --- a/src/Transform.cpp +++ b/src/Transform.cpp @@ -64,7 +64,7 @@ Tensor Transform::boost_spinor() const return Identity(2) * fcn::sqrt(0.5*(m_arg+1)) + sigma_dot_p(m_k)*fcn::sqrt(0.5*(m_arg-1)); } -Tensor Transform::operator()(const Representation& repr) const +Tensor Transform::operator()(const Representation& repr)const { Tensor::Index m,j,k; Tensor I2 = Identity(2); @@ -100,35 +100,40 @@ TransformSequence TransformSequence::inverse() const { TransformSequence rt; for( auto i = m_transforms.rbegin(); i != m_transforms.rend(); ++i ) - rt.add( i->inverse() ); + rt.push_back( i->inverse() ); return rt; } -Tensor TransformSequence::operator()( const Transform::Representation& repr ) +Tensor TransformSequence::operator()( const Transform::Representation& repr ) const { - if( m_cache[repr].nElements() != 1 ) - { - return m_cache[repr]; - } - if( m_transforms.size() == 0 ){ - if( repr == Transform::Representation::Spinor ) return Identity(2); - else return Identity(4); - } - Tensor::Index a,b,c; - Tensor rt = m_transforms[0](repr); - rt.st(); - for( size_t i = 1 ; i < m_transforms.size(); ++i ) + return m_cache[repr]; +} + +void TransformSequence::buildCache() +{ + for( auto repr : { Transform::Representation::Spinor, Transform::Representation::Bispinor, Transform::Representation::Vector } ) { - Tensor rti = m_transforms[i](repr); - rti.st(true); - rt = rti(a,b) * rt(b,c); + if( m_transforms.size() == 0 ){ + if( repr == Transform::Representation::Spinor ) m_cache[repr] = Identity(2); + m_cache[repr] = Identity(4); + } + else { + Tensor::Index a,b,c; + Tensor rt = m_transforms[0](repr); + rt.st(); + for( size_t i = 1 ; i < m_transforms.size(); ++i ) + { + Tensor rti = m_transforms[i](repr); + rti.st(true); + rt = rti(a,b) * rt(b,c); + } + m_cache[repr] = rt; + } } - m_cache[repr] = rt; - return rt; } Tensor TransformSequence::operator()( const Tensor& tensor, - const Transform::Representation& repr ) + const Transform::Representation& repr ) const { Tensor::Index a,b,c; auto seq = this->operator()(repr); @@ -136,26 +141,29 @@ Tensor TransformSequence::operator()( const Tensor& tensor, } Tensor Transform::operator()( const Tensor& tensor, - const Transform::Representation& repr ) const + const Transform::Representation& repr ) const { Tensor::Index a,b; auto seq = this->operator()(repr); return seq(a,b)*tensor(b); } -void TransformSequence::add( const Transform& transform ) +void TransformSequence::push_back( const Transform& transform ) { m_transforms.emplace_back( transform ); + buildCache(); } -void TransformSequence::add( const TransformSequence& transform ) +void TransformSequence::push_back( const TransformSequence& transform ) { for( auto& t : transform ) m_transforms.emplace_back(t); + buildCache(); } void TransformSequence::clear() { m_transforms.clear(); + buildCache(); } void TransformSequence::stepThrough(const Tensor& tensor, @@ -170,4 +178,38 @@ void TransformSequence::stepThrough(const Tensor& tensor, } } +TransformSequence::TransformSequence( const Transform& transform ) : m_transforms{transform} { + buildCache(); +} + +TransformSequence::TransformSequence( const TransformSequence& t1, const TransformSequence& t2) { + for( const auto& t : t1 ) m_transforms.push_back(t); + for( const auto& t : t2 ) m_transforms.push_back(t); + Tensor::Index a,b,c; + + for( auto repr : { Transform::Representation::Spinor, Transform::Representation::Bispinor, Transform::Representation::Vector } ) + { + auto r1 = t1( repr ); + auto r2 = t2( repr ); + m_cache[repr] = r2(a,b) * r1(b,c); + m_cache[repr].st(); + } +} + +TransformSequence::TransformSequence( const Transform& t1, const Transform& t2) : m_transforms{t1,t2} { + Tensor::Index a,b,c; + + for( auto repr : { Transform::Representation::Spinor, Transform::Representation::Bispinor, Transform::Representation::Vector } ) + { + auto r1 = t1(repr); + auto r2 = t2(repr); + m_cache[repr] = r2(a,b) * r1(b,c); + m_cache[repr].st(); + } +} + +TransformSequence::TransformSequence() +{ + buildCache(); +} diff --git a/src/Wigner.cpp b/src/Wigner.cpp index ecbc091ddfe..e098175b9c6 100644 --- a/src/Wigner.cpp +++ b/src/Wigner.cpp @@ -97,9 +97,9 @@ double AmpGen::CG( } TransformSequence AmpGen::wickTransform( const Tensor& P, - const Expression& mass, + const Particle& particle, const int& ve, - const bool& handleZero ) + DebugSymbols* db ) { Tensor x({1,0,0}, Tensor::dim(3)); Tensor y({0,1,0}, Tensor::dim(3)); @@ -111,17 +111,19 @@ TransformSequence AmpGen::wickTransform( const Tensor& P, Transform rot = ve == + 1 ? Transform( cos_theta, sin_phi*x - cos_phi*y, Transform::Type::Rotate) : Transform(-cos_theta, -sin_phi*x + cos_phi*y, Transform::Type::Rotate) ; - TransformSequence sequence; - sequence.add(rot); - if( ve == -1 ) sequence.add( Transform( -1, x, Transform::Type::Rotate ) ); - if( std::real(mass()) != 0. ){ + TransformSequence sequence(rot); + if( ve == -1 ) sequence.push_back( Transform( -1, x, Transform::Type::Rotate ) ); + + if( !particle.isStable() || !( particle.props()->isPhoton() || particle.props()->isNeutrino() ) ) + { + Expression mass = fcn::sqrt( particle.massSq() ); Transform boost( P[3]/mass, z, Transform::Type::Boost ); - sequence.add(boost); + return TransformSequence(sequence, boost); } - return sequence; + return TransformSequence(sequence); } -std::pair angCoordinates(const Tensor& P) +std::pair angCoordinates(const Tensor& P, DebugSymbols* db) { Expression pz = make_cse( P[2] / sqrt( P[0]*P[0] + P[1] * P[1] + P[2]*P[2] ) ); Expression pt2 = make_cse( P[0]*P[0] + P[1]*P[1] ); @@ -137,6 +139,9 @@ Expression AmpGen::wigner_D(const std::pair& P, { auto little_d = make_cse ( wigner_d( P.first, J, lA, lB ) ); if( J != 0 && db != nullptr ){ + db->emplace_back("cos(θ)", P.first ); + db->emplace_back("Ω", atan2( Imag(P.second), Real(P.second) ) ); + db->emplace_back("d[" + std::to_string(J) +", " + std::to_string(lA) +", " + std::to_string(lB) +"](θ)", little_d ); @@ -206,27 +211,40 @@ std::vector userHelicityCouplings( const std::string& key ){ return couplings; } +std::string index_string(const Particle& particle) +{ + if( particle.isStable() ) return std::to_string(particle.index()); + std::string f = "{"; + for( const auto& i : particle.daughters() ) f += index_string( *i ); + return f+ "}"; +} + Expression AmpGen::helicityAmplitude(const Particle& particle, - TransformSequence& parentFrame, + const TransformSequence& parentFrame, const double& Mz, DebugSymbols* db, int sgn, - std::map* cachePtr ) + TransformCache* cachePtr ) { - if( cachePtr == nullptr ) cachePtr = new std::map(); + if( cachePtr == nullptr ) cachePtr = new TransformCache(); if( particle.daughters().size() > 2 ) return 1; if( particle.daughters().size() == 1 ) return helicityAmplitude( *particle.daughter(0), parentFrame, Mz, db, sgn, cachePtr); Tensor::Index a,b,c; - auto myFrame = parentFrame; - if( particle.spin() == 0 ) myFrame.clear(); + // if( particle.props()->twoSpin() == 0 ) myFrame.clear(); Tensor pInParentFrame = parentFrame(particle.P()); pInParentFrame.st(); - auto my_sequence = wickTransform(pInParentFrame, fcn::sqrt(particle.massSq()), sgn, true); - if( cachePtr->count(&particle) != 0 ) my_sequence = (*cachePtr)[&particle]; - else (*cachePtr)[&particle] = my_sequence; + auto key = index_string(particle); + if( cachePtr->count(key) == 0 ) + { + if( ! particle.isHead() || NamedParameter("helicityAmplitude::MovingParent", false) ) + { + (*cachePtr)[key] = TransformSequence(parentFrame, wickTransform(pInParentFrame, particle, sgn, db) ); + } + else (*cachePtr)[key] = TransformSequence(); + } + const TransformSequence& myFrame = (*cachePtr)[key]; - if( ! particle.isHead() ) myFrame.add( my_sequence ); if( particle.isStable() ) { if( particle.props()->twoSpin() == 0 ) return Mz==0; // a scalar @@ -272,7 +290,8 @@ Expression AmpGen::helicityAmplitude(const Particle& particle, vectorToString( particle_couplings, ", ", []( auto& ls ){ return "("+std::to_string(int(ls.first)) + ", " + std::to_string(ls.second) +")";} ) ); } Expression total = 0; - std::pair hco = angCoordinates( myFrame(d1.P()) ); + + std::pair hco = angCoordinates( myFrame(d1.P()) , db); for( auto& coupling : recoupling_constants ) { auto dm = coupling.m1 - coupling.m2; From c3e827ebbfc7b8d3d834be1aa9a371a7552b6c39 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 28 May 2020 14:48:54 +0200 Subject: [PATCH 204/250] fix fitting in scalar build --- AmpGen/CompiledExpressionBase.h | 2 +- AmpGen/EventListSIMD.h | 6 +- AmpGen/MinuitParameter.h | 4 +- AmpGen/OptionsParser.h | 1 - AmpGen/Store.h | 15 +- AmpGen/simd/avx2d_types.h | 7 +- AmpGen/simd/avx2f_types.h | 95 ++++- AmpGen/simd/avx_mathfun.h | 727 -------------------------------- AmpGen/simd/utils.h | 6 +- README.md | 13 +- README.tex.md | 19 +- apps/Generator.cpp | 33 +- src/CompilerWrapper.cpp | 2 +- src/EventList.cpp | 4 +- src/EventType.cpp | 3 + src/Integrator.cpp | 2 +- src/MinuitParameter.cpp | 7 +- src/Particle.cpp | 17 +- src/PolarisedSum.cpp | 13 +- test/test_avx2d.cpp | 2 +- 20 files changed, 183 insertions(+), 795 deletions(-) delete mode 100644 AmpGen/simd/avx_mathfun.h diff --git a/AmpGen/CompiledExpressionBase.h b/AmpGen/CompiledExpressionBase.h index 691f1f94685..ab81672d567 100644 --- a/AmpGen/CompiledExpressionBase.h +++ b/AmpGen/CompiledExpressionBase.h @@ -72,7 +72,7 @@ namespace AmpGen std::vector> m_cacheTransfers; std::shared_ptr m_resolver; std::vector m_additionalHeaders; - bool m_enableBatch = {false}; + bool m_enableBatch = {true}; private: void addDebug( std::ostream& stream ) const; void addDependentExpressions( std::ostream& stream, size_t& sizeOfStream ) const; diff --git a/AmpGen/EventListSIMD.h b/AmpGen/EventListSIMD.h index 9c7900dd507..487f7898cef 100644 --- a/AmpGen/EventListSIMD.h +++ b/AmpGen/EventListSIMD.h @@ -67,7 +67,7 @@ namespace AmpGen float_v weight(const unsigned& p) const { return m_weights[p]; } float_v genPDF(const unsigned& p) const { return m_genPDF[p]; } - void setWeight( const unsigned& block, const float_v& w, const float_v& g=1) + void setWeight( const unsigned& block, const float_v& w, const float_v& g=1.f) { m_weights[block] = w; m_genPDF[block] = g; @@ -75,8 +75,8 @@ namespace AmpGen void resize( const unsigned nEvents ) { m_data = Store( nEvents, m_eventType.eventSize() ); - m_weights.resize( aligned_size(), 1); - m_genPDF.resize( aligned_size(), 1 ); + m_weights.resize( aligned_size(), 1.f); + m_genPDF.resize( aligned_size(), 1.f ); } const Event operator[]( const size_t&) const; std::array::value> scatter(unsigned) const; diff --git a/AmpGen/MinuitParameter.h b/AmpGen/MinuitParameter.h index 355e6fb3b65..6dec82882e1 100644 --- a/AmpGen/MinuitParameter.h +++ b/AmpGen/MinuitParameter.h @@ -36,7 +36,7 @@ namespace AmpGen double errNeg() const; double* vp() { return &m_meanResult ; } - void setInit( const double& init ); + void setInit( const double& init, const double& step=-1 ); void setStepInit( const double& si ); void setFree() ; void scaleStep( const double& sf ); @@ -73,7 +73,7 @@ namespace AmpGen MinuitProxy(MinuitParameter* param = nullptr, const double& value=0) : m_parameter(param), m_value(value) { update(); } MinuitParameter* operator->() { return m_parameter; } const MinuitParameter* operator->() const { return m_parameter; } - private: +src/EventType.cpp private: MinuitParameter* m_parameter{nullptr}; double m_value; }; diff --git a/AmpGen/OptionsParser.h b/AmpGen/OptionsParser.h index 8bf2a2ca12a..2350fa03141 100644 --- a/AmpGen/OptionsParser.h +++ b/AmpGen/OptionsParser.h @@ -28,7 +28,6 @@ namespace AmpGen iterator end(); const_iterator begin() const; const_iterator end() const; - private: std::map> m_parsedLines; bool m_printHelp = {false}; diff --git a/AmpGen/Store.h b/AmpGen/Store.h index 8686a91d333..425b29433fd 100644 --- a/AmpGen/Store.h +++ b/AmpGen/Store.h @@ -132,6 +132,8 @@ namespace AmpGen { //auto& [p0, s] = f->second; /// bug in the C++ standard. Such fun. auto p0 = f->second.first; auto s = f->second.second; + DEBUG("Updating: " << fcn.name() << " index = " << p0 << " size_of = " << s << " on store: " << size() << " blocks = " << nBlocks() << " fields = " << nFields () ); + if constexpr( std::is_same< typename functor_type::return_type, void >::value ) { @@ -165,9 +167,12 @@ namespace AmpGen { std::map> m_index; }; } -// using aos_store = AmpGen::Store; -// using soa_store = AmpGen::Store; -// -// ENABLE_DEBUG(aos_store) -// ENABLE_DEBUG(soa_store) +#if DEBUG_LEVEL ==1 +using aos_store = AmpGen::Store; +using soa_store = AmpGen::Store; + +ENABLE_DEBUG(aos_store) +ENABLE_DEBUG(soa_store) +#endif + #endif diff --git a/AmpGen/simd/avx2d_types.h b/AmpGen/simd/avx2d_types.h index 7293f30118d..0e07026d45c 100644 --- a/AmpGen/simd/avx2d_types.h +++ b/AmpGen/simd/avx2d_types.h @@ -9,10 +9,6 @@ #include #if USE_MVEC -// extern "C" __m256d _ZGVcN4v_cos(__m256d x); -// extern "C" __m256d _ZGVcN4v_sin(__m256d x); -// extern "C" __m256d _ZGVcN4v_exp(__m256d x); -// extern "C" __m256d _ZGVcN4v_log(__m256d x); extern "C" void _ZGVdN4vvv_sincos(__m256d x, __m256i ptrs, __m256i ptrc); #endif @@ -188,8 +184,7 @@ namespace AmpGen { inline complex_v select(const real_v& mask, const complex_v& a, const real_v& b ) { return complex_v( select(mask, a.re, b ) , select(mask, a.im, 0.f) ); } inline complex_v select(const bool& mask , const complex_v& a, const complex_v& b ) { return mask ? a : b; } inline complex_v exp( const complex_v& v ){ - real_v c, s; - sincos( v.im, c, s ); + auto [s,c] = sincos( v.im); return exp(v.re) * complex_v(c, s); } inline complex_v sqrt( const complex_v& v ) diff --git a/AmpGen/simd/avx2f_types.h b/AmpGen/simd/avx2f_types.h index 6ddd78327fd..096f2058cdc 100644 --- a/AmpGen/simd/avx2f_types.h +++ b/AmpGen/simd/avx2f_types.h @@ -5,11 +5,25 @@ #include #include #include -#include "AmpGen/simd/avx_mathfun.h" #include +#if USE_MVEC +extern "C" void _ZGVdN8vvv_sincos(__m256 x, __m256i ptrs, __m256i ptrc); +#endif + +#if USE_MVEC +#define libmvec_alias( function_name) \ + extern "C" __m256 _ZGVcN8v_##function_name(__m256 x); \ + inline real_v function_name( const real_v& v ){ return _ZGVcN8v_##function_name (v) ; } +#else +#define libmvec_alias( F ) \ + inline real_v F( const real_v& v ){ auto arr = v.to_array(); return real_v( \ + std::F(arr[0]), std::F(arr[1]), std::F(arr[2]), std::F(arr[3]), \ + std::F(arr[4]), std::F(arr[5]), std::F(arr[6]), std::F(arr[7]) ) ; } +#endif + namespace AmpGen { - namespace AVX2 { + namespace AVX2f { struct real_v { __m256 data; static constexpr unsigned size = 8 ; @@ -19,6 +33,12 @@ namespace AmpGen { real_v(const float& f ) : data( _mm256_set1_ps(f) ) {} real_v(const double& f ) : data( _mm256_set1_ps( float(f) )) {} real_v(const float* f ) : data( _mm256_loadu_ps( f ) ) {} + real_v(const float& x0, const float& x1, const float& x2, const float& x3, + const float& x4, const float& x5, const float& x6, const float& x7) + { + data = _mm256_set_ps(x0,x1,x2,x3,x4,x5,x6,x7); + } + void store( float* ptr ) const { _mm256_storeu_ps( ptr, data ); } std::array to_array() const { std::array b; store( &b[0] ); return b; } float at(const unsigned i) const { return to_array()[i] ; } @@ -44,11 +64,36 @@ namespace AmpGen { inline real_v operator>( const real_v& lhs, const real_v& rhs ) { return _mm256_cmp_ps( lhs, rhs, _CMP_GT_OS ); } inline real_v operator==( const real_v& lhs, const real_v& rhs ){ return _mm256_cmp_ps( lhs, rhs, _CMP_EQ_OS ); } inline real_v sqrt( const real_v& v ) { return _mm256_sqrt_ps(v); } - inline real_v sin( const real_v& v ) { return sin256_ps(v) ; } - inline real_v cos( const real_v& v ) { return cos256_ps(v) ; } - inline real_v tan( const real_v& v ) { real_v s; real_v c; sincos256_ps(v, (__m256*)&s, (__m256*)&c) ; return s/c; } - inline real_v log( const real_v& v ) { return log256_ps(v) ; } - inline real_v exp( const real_v& v ) { return exp256_ps(v) ; } + libmvec_alias(sin) + libmvec_alias(cos) + libmvec_alias(exp) + libmvec_alias(log) + + inline void sincos( const real_v& v, real_v& s, real_v& c ) + { +#if USE_MVEC + __m256i sp = _mm256_add_epi64(_mm256_set1_epi32x((uint64_t)&s),_mm256_set_epi32x(28,24,20,16,12,8,4,0)); + __m256i cp = _mm256_add_epi64(_mm256_set1_epi32x((uint64_t)&c),_mm256_set_epi32x(28,24,20,16,12,8,4,0)); + _ZGVdN8vvv_sincos(v,sp,cp); +#else + s = sin(v); + c = cos(v); +#endif + } + inline std::pair sincos( const real_v& v ) + { + std::pair rt; + sincos( v, rt.first, rt.second ); + return rt; + } + inline real_v tan( const real_v& v ) + { + auto [s,c] = sincos( v ); + return s / c ; + } + + + inline real_v abs ( const real_v& v ) { return v & _mm256_castsi256_ps( _mm256_set1_epi32( 0x7FFFFFFF ) ); } inline real_v select(const real_v& mask, const real_v& a, const real_v& b ) { return _mm256_blendv_ps( b, a, mask ); } inline real_v select(const bool& mask , const real_v& a, const real_v& b ) { return mask ? a : b; } @@ -57,9 +102,27 @@ namespace AmpGen { for( unsigned i = 0 ; i != 8 ; ++i ) rt[i] = std::atan2( by[i] , bx[i] ); return real_v (rt.data() ); } +// inline real_v gather( const double* base_addr, const real_v& offsets) +// { +// auto addr_avx =_mm256_cvtps_epi32(offsets); +// std::array addr; +// _mm256_storeu_ps( addr.data(), _mm256_cvtps_epi32(offsets) ); +// return real_v( +// base_addr[addr[0]], base_addr[addr[1]],base_addr[addr[2]],base_addr[addr[3]], +// base_addr[addr[4]], base_addr[addr[5]],base_addr[addr[6]],base_addr[addr[7]] ); +// +// //return _mm256_i32gather_ps(base_addr, _mm256_cvtps_epi32(offsets),sizeof(double)); +// } + inline real_v fmadd( const real_v& a, const real_v& b, const real_v& c ) { - return _mm256_fmadd_ps(a, b, c ); + return _mm256_fmadd_ps(a, b, c); + } + inline real_v remainder( const real_v& a, const real_v& b ){ return a - real_v(_mm256_round_ps(a/b, _MM_FROUND_TO_NEG_INF)) * b; } + inline real_v fmod( const real_v& a, const real_v& b ) + { + auto r = remainder( abs(a), abs(b) ); + return select( a > 0., r, -r ); } struct complex_v { real_v re; @@ -76,12 +139,18 @@ namespace AmpGen { complex_v( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} complex_v( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} const std::complex at(const unsigned i) const { return std::complex(re.to_array()[i], im.to_array()[i]) ; } - void store( float* sre, float* sim ){ re.store(sre); im.store(sim); } - void store( std::complex* r ){ + void store( float* sre, float* sim ) const { re.store(sre); im.store(sim); } + void store( std::complex* r ) const { auto re_arr = re.to_array(); auto im_arr = im.to_array(); for( unsigned i = 0 ; i != re_arr.size(); ++i ) r[i] = std::complex( re_arr[i], im_arr[i] ); } + auto to_array() const + { + std::array rt; + store( rt.data() ); + return rt; + } }; inline std::ostream& operator<<( std::ostream& os, const real_v& obj ) { @@ -113,9 +182,13 @@ namespace AmpGen { inline complex_v select(const real_v& mask, const complex_v& a, const real_v& b ) { return complex_v( _mm256_blendv_ps( b, a.re, mask ), _mm256_blendv_ps( real_v(0.f), a.im, mask ) ); } inline complex_v select(const bool& mask , const complex_v& a, const complex_v& b ) { return mask ? a : b; } inline complex_v exp( const complex_v& v ){ - real_v s; real_v c; sincos256_ps(v.im, (__m256*)&s, (__m256*)&c) ; + auto [s,c] = sincos( v.im ); return exp( v.re ) * complex_v(c, s); } + inline complex_v log( const complex_v& v ) + { + return complex_v( log( v.re ) , atan2(v.im, v.re) ); + } inline std::ostream& operator<<( std::ostream& os, const complex_v& obj ) { return os << "( "<< obj.re << ") (" << obj.im << ")"; } #pragma omp declare reduction(+: real_v: \ omp_out = omp_out + omp_in) diff --git a/AmpGen/simd/avx_mathfun.h b/AmpGen/simd/avx_mathfun.h deleted file mode 100644 index 918a7a35f42..00000000000 --- a/AmpGen/simd/avx_mathfun.h +++ /dev/null @@ -1,727 +0,0 @@ -#ifndef AMPGEN_AVX_MATHFUN_H -#define AMPGEN_AVX_MATHFUN_H 1 - -/* - AVX implementation of sin, cos, sincos, exp and log - - Based on "sse_mathfun.h", by Julien Pommier - http://gruntthepeon.free.fr/ssemath/ - - Copyright (C) 2012 Giovanni Garberoglio - Interdisciplinary Laboratory for Computational Science (LISC) - Fondazione Bruno Kessler and University of Trento - via Sommarive, 18 - I-38123 Trento (Italy) - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - (this is the zlib license) - - modified 8/4/2020: inline all functions, as they end up wrapped anyway -*/ - -#include - -/* yes I know, the top of this file is quite ugly */ -# define ALIGN32_BEG -# define ALIGN32_END __attribute__((aligned(32))) - -/* __m128 is ugly to write */ -typedef __m256 v8sf; // vector of 8 float (avx) -typedef __m256i v8si; // vector of 8 int (avx) -typedef __m128i v4si; // vector of 8 int (avx) - -#define _PI32AVX_CONST(Name, Val) \ - static const ALIGN32_BEG int _pi32avx_##Name[4] ALIGN32_END = { Val, Val, Val, Val } - -_PI32AVX_CONST(1, 1); -_PI32AVX_CONST(inv1, ~1); -_PI32AVX_CONST(2, 2); -_PI32AVX_CONST(4, 4); - - -/* declare some AVX constants -- why can't I figure a better way to do that? */ -#define _PS256_CONST(Name, Val) \ - static const ALIGN32_BEG float _ps256_##Name[8] ALIGN32_END = { Val, Val, Val, Val, Val, Val, Val, Val } -#define _PI32_CONST256(Name, Val) \ - static const ALIGN32_BEG int _pi32_256_##Name[8] ALIGN32_END = { Val, Val, Val, Val, Val, Val, Val, Val } -#define _PS256_CONST_TYPE(Name, Type, Val) \ - static const ALIGN32_BEG Type _ps256_##Name[8] ALIGN32_END = { Val, Val, Val, Val, Val, Val, Val, Val } - -_PS256_CONST(1 , 1.0f); -_PS256_CONST(0p5, 0.5f); -/* the smallest non denormalized float number */ -_PS256_CONST_TYPE(min_norm_pos, int, 0x00800000); -_PS256_CONST_TYPE(mant_mask, int, 0x7f800000); -_PS256_CONST_TYPE(inv_mant_mask, int, ~0x7f800000); - -_PS256_CONST_TYPE(sign_mask, int, (int)0x80000000); -_PS256_CONST_TYPE(inv_sign_mask, int, ~0x80000000); - -_PI32_CONST256(0, 0); -_PI32_CONST256(1, 1); -_PI32_CONST256(inv1, ~1); -_PI32_CONST256(2, 2); -_PI32_CONST256(4, 4); -_PI32_CONST256(0x7f, 0x7f); - -_PS256_CONST(cephes_SQRTHF, 0.707106781186547524); -_PS256_CONST(cephes_log_p0, 7.0376836292E-2); -_PS256_CONST(cephes_log_p1, - 1.1514610310E-1); -_PS256_CONST(cephes_log_p2, 1.1676998740E-1); -_PS256_CONST(cephes_log_p3, - 1.2420140846E-1); -_PS256_CONST(cephes_log_p4, + 1.4249322787E-1); -_PS256_CONST(cephes_log_p5, - 1.6668057665E-1); -_PS256_CONST(cephes_log_p6, + 2.0000714765E-1); -_PS256_CONST(cephes_log_p7, - 2.4999993993E-1); -_PS256_CONST(cephes_log_p8, + 3.3333331174E-1); -_PS256_CONST(cephes_log_q1, -2.12194440e-4); -_PS256_CONST(cephes_log_q2, 0.693359375); - -#ifndef __AVX2__ - -typedef union imm_xmm_union { - v8si imm; - v4si xmm[2]; -} imm_xmm_union; - -#define COPY_IMM_TO_XMM(imm_, xmm0_, xmm1_) { \ - imm_xmm_union u __attribute__((aligned(32))); \ - u.imm = imm_; \ - xmm0_ = u.xmm[0]; \ - xmm1_ = u.xmm[1]; \ -} - -#define COPY_XMM_TO_IMM(xmm0_, xmm1_, imm_) { \ - imm_xmm_union u __attribute__((aligned(32))); \ - u.xmm[0]=xmm0_; u.xmm[1]=xmm1_; imm_ = u.imm; \ - } - - -#define AVX2_BITOP_USING_SSE2(fn) \ -static inline v8si avx2_mm256_##fn(v8si x, int a) \ -{ \ - /* use SSE2 instruction to perform the bitop AVX2 */ \ - v4si x1, x2; \ - v8si ret; \ - COPY_IMM_TO_XMM(x, x1, x2); \ - x1 = _mm_##fn(x1,a); \ - x2 = _mm_##fn(x2,a); \ - COPY_XMM_TO_IMM(x1, x2, ret); \ - return(ret); \ -} - -//#warning "Using SSE2 to perform AVX2 bitshift ops" -AVX2_BITOP_USING_SSE2(slli_epi32) -AVX2_BITOP_USING_SSE2(srli_epi32) - -#define AVX2_INTOP_USING_SSE2(fn) \ -static inline v8si avx2_mm256_##fn(v8si x, v8si y) \ -{ \ - /* use SSE2 instructions to perform the AVX2 integer operation */ \ - v4si x1, x2; \ - v4si y1, y2; \ - v8si ret; \ - COPY_IMM_TO_XMM(x, x1, x2); \ - COPY_IMM_TO_XMM(y, y1, y2); \ - x1 = _mm_##fn(x1,y1); \ - x2 = _mm_##fn(x2,y2); \ - COPY_XMM_TO_IMM(x1, x2, ret); \ - return(ret); \ -} - -//#warning "Using SSE2 to perform AVX2 integer ops" -AVX2_INTOP_USING_SSE2(and_si128) -AVX2_INTOP_USING_SSE2(andnot_si128) -AVX2_INTOP_USING_SSE2(cmpeq_epi32) -AVX2_INTOP_USING_SSE2(sub_epi32) -AVX2_INTOP_USING_SSE2(add_epi32) -#define avx2_mm256_and_si256 avx2_mm256_and_si128 -#define avx2_mm256_andnot_si256 avx2_mm256_andnot_si128 -#else -#define avx2_mm256_slli_epi32 _mm256_slli_epi32 -#define avx2_mm256_srli_epi32 _mm256_srli_epi32 -#define avx2_mm256_and_si256 _mm256_and_si256 -#define avx2_mm256_andnot_si256 _mm256_andnot_si256 -#define avx2_mm256_cmpeq_epi32 _mm256_cmpeq_epi32 -#define avx2_mm256_sub_epi32 _mm256_sub_epi32 -#define avx2_mm256_add_epi32 _mm256_add_epi32 -#endif /* __AVX2__ */ - - -/* natural logarithm computed for 8 simultaneous float - return NaN for x <= 0 -*/ -inline v8sf log256_ps(v8sf x) { - v8si imm0; - v8sf one = *(v8sf*)_ps256_1; - - //v8sf invalid_mask = _mm256_cmple_ps(x, _mm256_setzero_ps()); - v8sf invalid_mask = _mm256_cmp_ps(x, _mm256_setzero_ps(), _CMP_LE_OS); - - x = _mm256_max_ps(x, *(v8sf*)_ps256_min_norm_pos); /* cut off denormalized stuff */ - - // can be done with AVX2 - imm0 = avx2_mm256_srli_epi32(_mm256_castps_si256(x), 23); - - /* keep only the fractional part */ - x = _mm256_and_ps(x, *(v8sf*)_ps256_inv_mant_mask); - x = _mm256_or_ps(x, *(v8sf*)_ps256_0p5); - - // this is again another AVX2 instruction - imm0 = avx2_mm256_sub_epi32(imm0, *(v8si*)_pi32_256_0x7f); - v8sf e = _mm256_cvtepi32_ps(imm0); - - e = _mm256_add_ps(e, one); - - /* part2: - if( x < SQRTHF ) { - e -= 1; - x = x + x - 1.0; - } else { x = x - 1.0; } - */ - //v8sf mask = _mm256_cmplt_ps(x, *(v8sf*)_ps256_cephes_SQRTHF); - v8sf mask = _mm256_cmp_ps(x, *(v8sf*)_ps256_cephes_SQRTHF, _CMP_LT_OS); - v8sf tmp = _mm256_and_ps(x, mask); - x = _mm256_sub_ps(x, one); - e = _mm256_sub_ps(e, _mm256_and_ps(one, mask)); - x = _mm256_add_ps(x, tmp); - - v8sf z = _mm256_mul_ps(x,x); - - v8sf y = *(v8sf*)_ps256_cephes_log_p0; - y = _mm256_mul_ps(y, x); - y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p1); - y = _mm256_mul_ps(y, x); - y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p2); - y = _mm256_mul_ps(y, x); - y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p3); - y = _mm256_mul_ps(y, x); - y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p4); - y = _mm256_mul_ps(y, x); - y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p5); - y = _mm256_mul_ps(y, x); - y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p6); - y = _mm256_mul_ps(y, x); - y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p7); - y = _mm256_mul_ps(y, x); - y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_log_p8); - y = _mm256_mul_ps(y, x); - - y = _mm256_mul_ps(y, z); - - tmp = _mm256_mul_ps(e, *(v8sf*)_ps256_cephes_log_q1); - y = _mm256_add_ps(y, tmp); - - - tmp = _mm256_mul_ps(z, *(v8sf*)_ps256_0p5); - y = _mm256_sub_ps(y, tmp); - - tmp = _mm256_mul_ps(e, *(v8sf*)_ps256_cephes_log_q2); - x = _mm256_add_ps(x, y); - x = _mm256_add_ps(x, tmp); - x = _mm256_or_ps(x, invalid_mask); // negative arg will be NAN - return x; -} - -_PS256_CONST(exp_hi, 88.3762626647949f); -_PS256_CONST(exp_lo, -88.3762626647949f); - -_PS256_CONST(cephes_LOG2EF, 1.44269504088896341); -_PS256_CONST(cephes_exp_C1, 0.693359375); -_PS256_CONST(cephes_exp_C2, -2.12194440e-4); - -_PS256_CONST(cephes_exp_p0, 1.9875691500E-4); -_PS256_CONST(cephes_exp_p1, 1.3981999507E-3); -_PS256_CONST(cephes_exp_p2, 8.3334519073E-3); -_PS256_CONST(cephes_exp_p3, 4.1665795894E-2); -_PS256_CONST(cephes_exp_p4, 1.6666665459E-1); -_PS256_CONST(cephes_exp_p5, 5.0000001201E-1); - -inline v8sf exp256_ps(v8sf x) { - v8sf tmp = _mm256_setzero_ps(), fx; - v8si imm0; - v8sf one = *(v8sf*)_ps256_1; - - x = _mm256_min_ps(x, *(v8sf*)_ps256_exp_hi); - x = _mm256_max_ps(x, *(v8sf*)_ps256_exp_lo); - - /* express exp(x) as exp(g + n*log(2)) */ - fx = _mm256_mul_ps(x, *(v8sf*)_ps256_cephes_LOG2EF); - fx = _mm256_add_ps(fx, *(v8sf*)_ps256_0p5); - - /* how to perform a floorf with SSE: just below */ - //imm0 = _mm256_cvttps_epi32(fx); - //tmp = _mm256_cvtepi32_ps(imm0); - - tmp = _mm256_floor_ps(fx); - - /* if greater, substract 1 */ - //v8sf mask = _mm256_cmpgt_ps(tmp, fx); - v8sf mask = _mm256_cmp_ps(tmp, fx, _CMP_GT_OS); - mask = _mm256_and_ps(mask, one); - fx = _mm256_sub_ps(tmp, mask); - - tmp = _mm256_mul_ps(fx, *(v8sf*)_ps256_cephes_exp_C1); - v8sf z = _mm256_mul_ps(fx, *(v8sf*)_ps256_cephes_exp_C2); - x = _mm256_sub_ps(x, tmp); - x = _mm256_sub_ps(x, z); - - z = _mm256_mul_ps(x,x); - - v8sf y = *(v8sf*)_ps256_cephes_exp_p0; - y = _mm256_mul_ps(y, x); - y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_exp_p1); - y = _mm256_mul_ps(y, x); - y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_exp_p2); - y = _mm256_mul_ps(y, x); - y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_exp_p3); - y = _mm256_mul_ps(y, x); - y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_exp_p4); - y = _mm256_mul_ps(y, x); - y = _mm256_add_ps(y, *(v8sf*)_ps256_cephes_exp_p5); - y = _mm256_mul_ps(y, z); - y = _mm256_add_ps(y, x); - y = _mm256_add_ps(y, one); - - /* build 2^n */ - imm0 = _mm256_cvttps_epi32(fx); - // another two AVX2 instructions - imm0 = avx2_mm256_add_epi32(imm0, *(v8si*)_pi32_256_0x7f); - imm0 = avx2_mm256_slli_epi32(imm0, 23); - v8sf pow2n = _mm256_castsi256_ps(imm0); - y = _mm256_mul_ps(y, pow2n); - return y; -} - -_PS256_CONST(minus_cephes_DP1, -0.78515625); -_PS256_CONST(minus_cephes_DP2, -2.4187564849853515625e-4); -_PS256_CONST(minus_cephes_DP3, -3.77489497744594108e-8); -_PS256_CONST(sincof_p0, -1.9515295891E-4); -_PS256_CONST(sincof_p1, 8.3321608736E-3); -_PS256_CONST(sincof_p2, -1.6666654611E-1); -_PS256_CONST(coscof_p0, 2.443315711809948E-005); -_PS256_CONST(coscof_p1, -1.388731625493765E-003); -_PS256_CONST(coscof_p2, 4.166664568298827E-002); -_PS256_CONST(cephes_FOPI, 1.27323954473516); // 4 / M_PI - - -/* evaluation of 8 sines at onces using AVX intrisics - - The code is the exact rewriting of the cephes sinf function. - Precision is excellent as long as x < 8192 (I did not bother to - take into account the special handling they have for greater values - -- it does not return garbage for arguments over 8192, though, but - the extra precision is missing). - - Note that it is such that sinf((float)M_PI) = 8.74e-8, which is the - surprising but correct result. - -*/ -inline v8sf sin256_ps(v8sf x) { // any x - v8sf xmm1, xmm2 = _mm256_setzero_ps(), xmm3, sign_bit, y; - v8si imm0, imm2; - -#ifndef __AVX2__ - v4si imm0_1, imm0_2; - v4si imm2_1, imm2_2; -#endif - - sign_bit = x; - /* take the absolute value */ - x = _mm256_and_ps(x, *(v8sf*)_ps256_inv_sign_mask); - /* extract the sign bit (upper one) */ - sign_bit = _mm256_and_ps(sign_bit, *(v8sf*)_ps256_sign_mask); - - /* scale by 4/Pi */ - y = _mm256_mul_ps(x, *(v8sf*)_ps256_cephes_FOPI); - - /* - Here we start a series of integer operations, which are in the - realm of AVX2. - If we don't have AVX, let's perform them using SSE2 directives - */ - -#ifdef __AVX2__ - /* store the integer part of y in mm0 */ - imm2 = _mm256_cvttps_epi32(y); - /* j=(j+1) & (~1) (see the cephes sources) */ - // another two AVX2 instruction - imm2 = avx2_mm256_add_epi32(imm2, *(v8si*)_pi32_256_1); - imm2 = avx2_mm256_and_si256(imm2, *(v8si*)_pi32_256_inv1); - y = _mm256_cvtepi32_ps(imm2); - - /* get the swap sign flag */ - imm0 = avx2_mm256_and_si256(imm2, *(v8si*)_pi32_256_4); - imm0 = avx2_mm256_slli_epi32(imm0, 29); - /* get the polynom selection mask - there is one polynom for 0 <= x <= Pi/4 - and another one for Pi/4 bool all_of( const simd_type& obj, const value_type& v ) { - if constexpr( ! is_vector_type::value ) return obj == v; - else return _mm256_movemask_pd( obj == v ) == 0xF; + if constexpr( size::value == 1 ) return obj == v; + if constexpr( size::value == 4 ) return _mm256_movemask_pd( obj == v ) == 0xF; + if constexpr( size::value == 8 ) return _mm256_movemask_ps( obj == v ) == 0xFF; + return false; } template bool all_of( const simd_type& obj) { diff --git a/README.md b/README.md index a862c53b3d2..7b00577c317 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,6 @@ There is at the time of writing only a master branch (FIXME) ##### Build requirements: * cmake >= 3.11.0 * C++ compiler with CXX standard >= 17 (gcc >= 8) - Defaults to Cxx17 * ROOT >= 6 with MathMore To (re)configure root with these options, use the additional command line options `-Dcxx14 -Dmathmore=ON` when configuring the installation of ROOT. @@ -39,6 +38,7 @@ There is at the time of writing only a master branch (FIXME) * OpenMP for multithreading * ROOT >= 6 with MathMore and Minuit2 enabled. The external version of Minuit2 provided as an external package of GooFit is used if the ROOT version is not unavailable. To (re)configure root with these options, use the additional command line options `-Dminuit2=ON -Dmathmore=ON` when configuring the installation of ROOT. +* libmvec for vectorised math operations #### Building The configuration of the AmpGen build is performed by cmake. @@ -81,7 +81,16 @@ In order to build stand-alone on LXPLUS, you will need a valid development envir source /cvmfs/sft.cern.ch/lcg/views/setupViews.sh LCG_94python3 x86_64-centos7-gcc8-opt ``` The LCG versions and CMTCONFIG may need to be updated over time. -The ROOT versions installed on cvmfs generally require C++17 support when building, i.e. when running cmake add the option `-DCMAKE_CXX_STANDARD=17`. + +#### Using AVX + +AmpGen (v > 2.0) can be setup to generate vectorised code for faster evaluation of amplitudes / computation of integrals on compatible hardware. +Such extensions can be enabled by setting the flag +``` +_DUSE_SIMD=AVX2d +``` +Which indicates that code should be generated using the AVX2 instruction set using double precision. +Single precision is also supported, but not recommended for fitting. ### Options files and decay descriptors diff --git a/README.tex.md b/README.tex.md index 1b5023c912c..46878dc36b6 100644 --- a/README.tex.md +++ b/README.tex.md @@ -84,6 +84,17 @@ All standalone programs can accept both options files and command line arguments They also support `--help` to print help for key arguments to the program. This will also run the program, as arguments can be defined throughout each of the programs rather than all defined at the beginning. +#### Using SIMD instructions. + +AmpGen (v > 2.0) can be setup to generate vectorised code for faster evaluation of amplitudes / computation of integrals on compatible hardware. +Such extensions can be enabled by setting the flag +``` +_DUSE_SIMD=AVX2d +``` +Which indicates that code should be generated using the AVX2 instruction set using double precision. +Single precision is also supported, but not recommended for fitting. + + ### Options files and decay descriptors Options files will generally contain the description of one or more particle decays, @@ -167,6 +178,12 @@ Several models for different @f$D^0@f$ decays published by the LHCb collaboratio ./Generator options/D02Kpipipi.opt --EventType "D0 K- pi+ pi+ pi-" --nEvents 1000000 ``` +#### Phase space generators + +Generating events consists of two phases. Firstly, the kinematics of candidates are generated according to some distribution, typically flat in the phase space. +The target distribution is then obtained using the accept-reject method, that is, for a candidate at position @$f + + ### Debugger The debugger application is a tool for producing verbose information debugging for amplitudes and models. It is used on an options file as @@ -277,7 +294,7 @@ AmpGen implements both the covariant tensor (or Rarita-Schwinger) and canonical Both formalisms refer to states of well-defined orbital angular momentum, as opposed to the helicity states, as the states with well-defined orbital angular momentum have a straightforward parity and momentum dependences. The default formalism is the covariant tensor formalism, but this can be switched to the canonical formalism changing the flag ``` -Particle::SpinFormalism Canonical ## default = Covariant +Particle::SpinFormalism Canonical ``` in the options file. The spin formalism for an individual decay chain can be specified by changing the attribute SpinFormalism in the decay descriptor. For example, diff --git a/apps/Generator.cpp b/apps/Generator.cpp index 00ea2e10643..1bc01fe1a8b 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -103,21 +103,21 @@ template void generateEvents( EventList& events { Generator signalGenerator(events.eventType(), rndm); signalGenerator.setBlockSize(blockSize); -// signalGenerator.setNormFlag(normalise); + signalGenerator.setNormFlag(normalise); signalGenerator.fillEventList(pdf, events, nEvents ); } else if( phsp_type == phspTypes::RecursivePhaseSpace ) { Generator signalGenerator( getTopology(pdf), events.eventType(), rndm ); signalGenerator.setBlockSize(blockSize); -// signalGenerator.setNormFlag(normalise); + signalGenerator.setNormFlag(normalise); signalGenerator.fillEventList(pdf, events, nEvents); } else if( phsp_type == phspTypes::TreePhaseSpace ) { Generator signalGenerator(getDecayChains(pdf), events.eventType(), rndm); signalGenerator.setBlockSize(blockSize); -// signalGenerator.setNormFlag(normalise); + signalGenerator.setNormFlag(normalise); signalGenerator.fillEventList(pdf, events, nEvents ); } else { @@ -134,26 +134,24 @@ int main( int argc, char** argv ) size_t blockSize = NamedParameter ("BlockSize", 5000000, "Number of events to generate per block" ); int seed = NamedParameter ("Seed" , 0, "Random seed used in event Generation" ); std::string outfile = NamedParameter("Output" , "Generate_Output.root" , "Name of output file" ); - auto pdfType = NamedParameter( "Type", pdfTypes::CoherentSum, optionalHelpString("Generator configuration to use:", - { {"CoherentSum" , "Full phase-space generator with (pseudo)scalar amplitude"} - , {"PolarisedSum" , "Full phase-space generator with particles carrying spin in the initial/final states"} - , {"FixedLib" , "Full phase-space generator with an amplitude from a precompiled library"}} ) ); + auto pdfType = NamedParameter( "Type", pdfTypes::CoherentSum, optionalHelpString("Type of PDF to use:", + { {"CoherentSum" , "Describes decays of a (pseudo)scalar particle to N pseudoscalars"} + , {"PolarisedSum" , "Describes the decay of a particle with spin to N particles carrying spin."} + , {"FixedLib" , "PDF to describe a decay from a precompiled library, such as those provided to GAUSS."}} ) ); auto phspType = NamedParameter( "PhaseSpace", phspTypes::PhaseSpace, optionalHelpString("Phase-space generator to use:", - { {"CoherentSum" , "Full phase-space generator with (pseudo)scalar amplitude"} - , {"PolarisedSum" , "Full phase-space generator with particles carrying spin in the initial/final states"} - , {"FixedLib" , "Full phase-space generator with an amplitude from a precompiled library"}} ) ); + { {"PhaseSpace" , "Phase space generation based on Raubold-Lynchi algorithm (recommended)."} + , {"TreePhaseSpace" , "Divides the phase-space into a series of quasi two-body phase-spaces for efficiently generating narrow states."} + , {"RecursivePhaseSpace", "Includes possible quasi-stable particles and the phase spaces of their decay products, such as Λ baryons."}} ) ); std::string lib = NamedParameter("Library","","Name of library to use for a fixed library generation"); size_t nBins = NamedParameter ("nBins" ,100, "Number of bins for monitoring plots." ); #ifdef _OPENMP unsigned int concurentThreadsSupported = std::thread::hardware_concurrency(); unsigned int nCores = NamedParameter( "nCores", concurentThreadsSupported, "Number of cores to use (OpenMP only)" ); - INFO("Using: " << nCores << " / " << concurentThreadsSupported << " threads" ); omp_set_num_threads( nCores ); omp_set_dynamic( 0 ); #endif - INFO("Writing output: " << outfile ); TRandom3 rand; rand.SetSeed( seed + 934534 ); @@ -171,12 +169,19 @@ int main( int argc, char** argv ) } else eventType = EventType( NamedParameter( "EventType" , "", "EventType to generate, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(), NamedParameter( "GenerateTimeDependent", false , "Flag to include possible time dependence of the amplitude") ); - - if ( NamedParameter( "conj", false ) == true ) { + + bool conj = NamedParameter("Conj",false, "Flag to generate the CP conjugate amplitude under the assumption of CP conservation"); + if ( conj == true ) { eventType = eventType.conj(); INFO( eventType ); AddCPConjugate(MPS); } + if( OptionsParser::printHelp() ) return 0; + + INFO("Writing output: " << outfile ); + #ifdef _OPENMP + INFO("Using: " << nCores << " / " << concurentThreadsSupported << " threads" ); + #endif INFO("Generating time-dependence? " << eventType.isTimeDependent() ); EventList accepted( eventType ); diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index 1cc55061d28..80962299085 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -54,7 +54,7 @@ void CompilerWrapper::generateSource( const CompiledExpressionBase& expression, std::ofstream output( filename ); for ( auto& include : m_includes ) output << "#include <" << include << ">\n"; if( expression.fcnSignature().find("AVX2d") != std::string::npos ) output << "#include \"AmpGen/simd/avx2d_types.h\"\n; using namespace AmpGen::AVX2d;\n" ; - else if( expression.fcnSignature().find("AVX2") != std::string::npos ) output << "#include \"AmpGen/simd/avx2_types.h\"\n; using namespace AmpGen::AVX2;\n;" ; + else if( expression.fcnSignature().find("AVX2f") != std::string::npos ) output << "#include \"AmpGen/simd/avx2f_types.h\"\n; using namespace AmpGen::AVX2f;\n;" ; else if( expression.fcnSignature().find("AVX512d") != std::string::npos ) output << "#include \"AmpGen/simd/avx512d_types.h\"\n; using namespace AmpGen::AVX512d;\n;" ; else if( expression.fcnSignature().find("AVX512") != std::string::npos ) output << "#include \"AmpGen/simd/avx512_types.h\"\n; using namespace AmpGen::AVX512;\n;" ; output << expression << std::endl; diff --git a/src/EventList.cpp b/src/EventList.cpp index 8fe00dcb738..db09d143e5d 100644 --- a/src/EventList.cpp +++ b/src/EventList.cpp @@ -124,8 +124,8 @@ void EventList::loadFromTree( TTree* tree, const ArgumentPack& args ) auto automaticOrdering = m_eventType.automaticOrdering(); for (const auto& evt : tr) { if( inputUnits != Units::GeV ) for( unsigned k = 0; k != eventFormat.size(); ++k ) temp[k] *= to_double(inputUnits); - if( idBranches.size() != 0 && !automaticOrdering(temp, ids) ) - WARNING("Failed to order event: " << evt ); + // if( idBranches.size() != 0 && !automaticOrdering(temp, ids) ) + // WARNING("Failed to order event: " << evt ); if( applySym ) symmetriser(temp); if( ! hasEnergy ){ for( unsigned int k = 0 ; k != m_eventType.size(); ++k ) diff --git a/src/EventType.cpp b/src/EventType.cpp index c111e0ced4d..06e3e1f33f6 100644 --- a/src/EventType.cpp +++ b/src/EventType.cpp @@ -20,12 +20,15 @@ #include "AmpGen/Utilities.h" #include "AmpGen/Units.h" #include "AmpGen/Event.h" +#include "AmpGen/OptionsParser.h" using namespace AmpGen; std::string convertTeXtoROOT(std::string input); EventType::EventType( const std::vector& particleNames, const bool& isTD ) : m_timeDependent( isTD ) { + if ( OptionsParser::printHelp() ) return; + if ( particleNames.size() < 3 ) { // Mother plus two daughters minimum required ERROR( "Not enough particles in event type: " << particleNames[0] << " size = " << particleNames.size() ); throw std::runtime_error( "Not enough particles listed in particle names! Was it defined?" ); diff --git a/src/Integrator.cpp b/src/Integrator.cpp index 70da64875db..3736ef37a5d 100644 --- a/src/Integrator.cpp +++ b/src/Integrator.cpp @@ -52,7 +52,7 @@ void Integrator::integrateBlock() im = im + m_weight[i] * imag(c); #endif } - *m_integrals[roll].result = utils::sum_elements( complex_v(re, im) ) / m_norm; + *m_integrals[roll].result = complex_t(utils::sum_elements( complex_v(re, im) )) / m_norm; } m_counter = 0; } diff --git a/src/MinuitParameter.cpp b/src/MinuitParameter.cpp index 3c2d5941e97..896dc3a038d 100644 --- a/src/MinuitParameter.cpp +++ b/src/MinuitParameter.cpp @@ -57,7 +57,12 @@ void MinuitParameter::setFree() { INFO("Setting parameter: " << m_name << " free void MinuitParameter::setCurrentFitVal( double cfv ) { m_meanResult = cfv; } -void MinuitParameter::setInit( const double& val ) { m_meanInit = val; } +void MinuitParameter::setInit( const double& val, const double& step ) +{ + m_meanInit = val; + m_meanResult = val; + if( step != -1 ) m_stepInit = step; +} void MinuitParameter::setResult( double fitMean, double fitErr, double fitErrPos, double fitErrNeg ) { diff --git a/src/Particle.cpp b/src/Particle.cpp index 35d2ac2e2a7..784011c2748 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -411,8 +411,7 @@ Expression Particle::getExpression( DebugSymbols* db, const std::vector& st } } if ( includeSpin && m_spinFormalism == spinFormalism::Canonical ){ - TransformSequence t = TransformSequence(); - spinFactor = helicityAmplitude(*this, t, m_props->isBoson() ? polState() : double(polState())/2.0, db); + spinFactor = helicityAmplitude(*this, TransformSequence(), m_props->isBoson() ? polState() : double(polState())/2.0, db); } if( db != nullptr ){ std::string finalStateString=""; @@ -549,18 +548,18 @@ Tensor Particle::externalSpinTensor(const int& polState, DebugSymbols* db ) cons std::pair Particle::orbitalRange( const bool& conserveParity ) const { if( m_daughters.size() == 0 ) return {0, 0}; - if( m_daughters.size() == 1 ) return {0,0}; + if( m_daughters.size() == 1 ) return {0, 0}; if( m_daughters.size() != 2 ) { ERROR( "L not well defined for nDaughters == " << m_daughters.size() ); return {999, 998}; } const int S = m_props->twoSpin(); - const int s1 = daughter( 0 )->props()->twoSpin(); - const int s2 = daughter( 1 )->props()->twoSpin(); - int min = std::abs( S - s1 - s2 ); - if ( std::abs( S + s1 - s2 ) < min ) min = std::abs( S + s1 - s2 ); - if ( std::abs( S - s1 + s2 ) < min ) min = std::abs( S - s1 + s2 ); - int max = S + s1 + s2; + const int s1 = daughter(0)->props()->twoSpin(); + const int s2 = daughter(1)->props()->twoSpin(); + int min = std::abs( S - s1 - s2 ); + min = std::min(min, std::abs( S + s1 - s2 )); + min = std::min(min, std::abs( S - s1 + s2 )); + int max = S + s1 + s2; min /= 2; max /= 2; DEBUG( "Range = " << min << " -> " << max << " conserving parity ? " << conserveParity << " J = " << S << " s1= " << s1 << " s2= " << s2 ); diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 0684979664a..1db1caeb531 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -35,7 +35,9 @@ using namespace AmpGen; using namespace std::complex_literals; -// ENABLE_DEBUG( PolarisedSum ) +#if DEBUGLEVEL == 1 + ENABLE_DEBUG( PolarisedSum ) +#endif namespace AmpGen { make_enum(spaceType, spin, flavour) } @@ -202,9 +204,10 @@ void PolarisedSum::prepare() for_each_sequence(m_matrixElements.begin(), m_matrixElements.end(), flagUpdate, updateData, updateInteg); if( m_integrator.isReady() ) updateNorms(); std::for_each( m_matrixElements.begin(), m_matrixElements.end(), resetFlags ); -// if( m_nCalls % 10000 == 0 ) debug_norm(); + if constexpr( detail::debug_type::value ) + if( m_nCalls % 10000 == 0 ) debug_norm(); m_pdfCache.update(m_cache, m_probExpression); - DEBUG( "m_pdfCache[0] = " << m_pdfCache[0] << " w/o caching = " << (m_weight/m_norm) * getValNoCache(m_events->at(0))); + DEBUG( "m_pdfCache[0] = " << utils::at(m_pdfCache[0],0) << " w/o caching = " << getValNoCache(m_events->at(0)) << " w = " << m_weight << " N = " << m_norm ); m_nCalls++; } @@ -223,6 +226,7 @@ double PolarisedSum::operator()( const double*, const unsigned index ) const void PolarisedSum::debug_norm() { + if( !m_integrator.isReady() ) return; double norm_slow = 0; for( auto& evt : *m_integrator.events() ) norm_slow += evt.weight() * getValNoCache(evt) / evt.genPdf(); @@ -275,10 +279,9 @@ Tensor PolarisedSum::transitionMatrix() real_t PolarisedSum::operator()(const Event& evt) const { - return utils::at( m_pdfCache[ evt.index() / utils::size::value ], evt.index() % utils::size::value ); + return (m_weight/m_norm) * utils::at( m_pdfCache[ evt.index() / utils::size::value ], evt.index() % utils::size::value ); } - double PolarisedSum::norm() const { return m_norm; diff --git a/test/test_avx2d.cpp b/test/test_avx2d.cpp index 965b8426abd..a458fa294d9 100644 --- a/test/test_avx2d.cpp +++ b/test/test_avx2d.cpp @@ -7,7 +7,7 @@ namespace utf = boost::unit_test; -#if ENABLE_AVX +#if ENABLE_AVX2d #include "AmpGen/simd/utils.h" using namespace AmpGen; From 87d38388430a260f0ceaeda8f2773cb7ecf6e789 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 28 May 2020 15:23:42 +0200 Subject: [PATCH 205/250] fix fitting in scalar build --- AmpGen/MinuitParameter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AmpGen/MinuitParameter.h b/AmpGen/MinuitParameter.h index 6dec82882e1..dbdaadf10bf 100644 --- a/AmpGen/MinuitParameter.h +++ b/AmpGen/MinuitParameter.h @@ -73,7 +73,7 @@ namespace AmpGen MinuitProxy(MinuitParameter* param = nullptr, const double& value=0) : m_parameter(param), m_value(value) { update(); } MinuitParameter* operator->() { return m_parameter; } const MinuitParameter* operator->() const { return m_parameter; } -src/EventType.cpp private: + private: MinuitParameter* m_parameter{nullptr}; double m_value; }; From 07c4773c03e0c981e8ddcbae8eff7b447cbdd7e8 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Sun, 7 Jun 2020 23:43:11 +0200 Subject: [PATCH 206/250] improve customised particles, improve compiler threading --- AmpGen/CompiledExpression.h | 58 ++++++++++++++------------- AmpGen/EventList.h | 8 +++- AmpGen/FitResult.h | 4 +- AmpGen/OptionsParser.h | 5 ++- AmpGen/ParticleProperties.h | 49 +++++++++++------------ AmpGen/ParticlePropertiesList.h | 1 + apps/DataConverter.cpp | 12 ++---- src/CoherentSum.cpp | 2 +- src/EventList.cpp | 3 +- src/OptionsParser.cpp | 56 ++++++++++++-------------- src/Particle.cpp | 8 ++-- src/ParticleProperties.cpp | 59 +++++++++++++++++++++------ src/ParticlePropertiesList.cpp | 22 +++++++++++ src/PolarisedSum.cpp | 70 ++++++++++++++++----------------- src/ThreeBodyCalculators.cpp | 4 +- 15 files changed, 211 insertions(+), 150 deletions(-) diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index 6b3812564b6..1c08c59bd78 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -13,6 +13,8 @@ #include #include #include +#include +#include "ArgumentPack.h" namespace AmpGen { @@ -21,11 +23,17 @@ namespace AmpGen usually this is a std::complex, but in principal support also exists for computing coupled channel propagators (i.e. returning array types) */ + + + namespace detail { template struct size_of { static constexpr unsigned value = sizeof(T); }; template <> struct size_of { static constexpr unsigned value = 0; } ; } + DECLARE_ARGUMENT(disableBatch, bool); + template class CompiledExpression; + template class CompiledExpression : public CompiledExpressionBase @@ -37,18 +45,26 @@ namespace AmpGen DynamicFCN>(ARGS...)> m_fdb; std::vector m_externals = {}; bool m_hasExternalsChanged = {false}; - + public: typedef RETURN_TYPE return_type; - - CompiledExpression( const Expression& expression, - const std::string& name, - const std::map& evtMapping = - std::map(), - const DebugSymbols& db = {}, - const MinuitParameterSet* mps = nullptr ) - : CompiledExpressionBase( expression, name, db, evtMapping ) + + template + CompiledExpression( const Expression& expression, const std::string& name, const namedArgs&... args ) : CompiledExpressionBase(expression, name) { + const MinuitParameterSet* mps = nullptr; + auto process_argument = [&]( const auto& arg ) + { + if constexpr( std::is_convertible::value ) this->m_db = arg; + else if constexpr( std::is_convertible>::value ) this->m_evtMap = arg; + else if constexpr( std::is_convertible::value ) this->m_enableBatch = false; + else if constexpr( std::is_convertible::value ) mps = arg; + else if constexpr( std::is_convertible::value ) mps = arg; + else if constexpr( std::is_convertible::value ) mps = &arg; + else ERROR("Unrecognised argument: " << type_string(arg) ); + }; + for_each( std::tuple(args...), process_argument); + DEBUG("Made expression: " << m_name << " " << progName() << " " << mps << " batch enabled ? " << this->m_enableBatch ); resolve(mps); } @@ -145,7 +161,8 @@ namespace AmpGen DEBUG( "Compiling " << name() << " = " << hash() ); stream << "extern \"C\" " << returnTypename() << " " << progName() << "_wParams" << "( const double*__restrict__ E ){" << std::endl; - stream << " double externalParameters [] = {" << (m_externals.size() == 0 ? "0" : vectorToString(m_externals,", ") ) <<"};\n" ; + stream << " double externalParameters [] = {" << + (m_externals.size() == 0 ? "0" : vectorToString(m_externals,", ", [](auto& line){ return std::to_string(line); }) ) <<"};\n" ; stream << " return " << progName() << "( externalParameters, E ); // E is P \n}\n"; } @@ -213,8 +230,7 @@ namespace AmpGen return rt; } - template - CompiledExpression + template CompiledExpression make_expression( const Expression& expression, const std::string& name , const bool& verbose=false) { CompiledExpression rt(expression,name); @@ -222,25 +238,13 @@ namespace AmpGen rt.prepare(); return rt; } - template + template CompiledExpression make_expression( const Expression& expression, const std::string& name, - const MinuitParameterSet& mps ) - { - CompiledExpression rt(expression,name,{},{},&mps); - rt.compile(); - rt.prepare(); - return rt; - } - template - CompiledExpression - make_expression( const Expression& expression, - const std::string& name, - const std::map & evtMap, - const MinuitParameterSet& mps ) + const arg_types&... args) { - CompiledExpression rt(expression,name,evtMap,{},&mps); + CompiledExpression rt(expression,name,args...); rt.compile(); rt.prepare(); return rt; diff --git a/AmpGen/EventList.h b/AmpGen/EventList.h index 8d3f742cf6c..8495845e2dc 100644 --- a/AmpGen/EventList.h +++ b/AmpGen/EventList.h @@ -75,6 +75,12 @@ namespace AmpGen const double* block(const unsigned pos) const { return m_data[pos].address(); } real_t weight( const size_t& pos) const { return m_data[pos].weight(); } real_t genPDF( const size_t& pos) const { return m_data[pos].genPdf(); } + unsigned key(const std::string& key) const + { + auto it = m_extensions.find(key); + if( it == m_extensions.end() ) return m_data[0].size() - 1; + return it->second; + } void reserve( const size_t& size ); void resize ( const size_t& size ); void push_back( const Event& evt ); @@ -134,7 +140,7 @@ namespace AmpGen { unsigned currentSize = size(); m_data.erase( std::remove_if( m_data.begin(), m_data.end(), fcn ) , m_data.end() ); - INFO("Filter removes: " << currentSize - size() << " / " << currentSize << " events"); + INFO("Filter retains " << size() << " / " << currentSize << " events"); } template unsigned count( functor&& fcn ) const diff --git a/AmpGen/FitResult.h b/AmpGen/FitResult.h index 01c09fd83e2..932eab0f979 100644 --- a/AmpGen/FitResult.h +++ b/AmpGen/FitResult.h @@ -2,6 +2,7 @@ #define AMPGEN_FITRESULT_H #include "TMatrixD.h" +#include "TClass.h" #include "AmpGen/FitFraction.h" #include "AmpGen/MinuitParameter.h" @@ -15,6 +16,7 @@ namespace AmpGen class FitResult { public: + ~FitResult(){}; FitResult(); explicit FitResult( const FitResult& other ); explicit FitResult( const std::string& filename ); @@ -56,7 +58,7 @@ namespace AmpGen LinearErrorPropagator getErrorPropagator( const bool& extended = false ) const; private: - MinuitParameterSet* m_mps; + MinuitParameterSet* m_mps = {nullptr}; double m_chi2 = {0}; double m_LL = {-999}; double m_nBins = {0}; diff --git a/AmpGen/OptionsParser.h b/AmpGen/OptionsParser.h index 2350fa03141..ec9dc04832d 100644 --- a/AmpGen/OptionsParser.h +++ b/AmpGen/OptionsParser.h @@ -6,6 +6,7 @@ #include #include #include +#include namespace AmpGen { @@ -30,14 +31,16 @@ namespace AmpGen const_iterator end() const; private: std::map> m_parsedLines; + std::map)> > m_keywords; bool m_printHelp = {false}; bool m_quiet = {false}; static OptionsParser* gOptionsParser; - OptionsParser() = default; + OptionsParser(); bool ignoreThisLine( const std::string& line ); void readStream( std::istream& is ); std::vector makeParsedStrings( const std::string& line, int& braceDepth ) const; + void addArg(const std::vector& tokens ); }; } // namespace AmpGen #endif diff --git a/AmpGen/ParticleProperties.h b/AmpGen/ParticleProperties.h index fc16668483f..74adeab6dd3 100644 --- a/AmpGen/ParticleProperties.h +++ b/AmpGen/ParticleProperties.h @@ -44,8 +44,8 @@ namespace AmpGen int twoSpin() const { return m_twoSpin; } ///< Returns twice the spin of the particle int charge() const { return m_charge; } ///< Returns the (electrical) charge of the particle char S() const { return m_status; } ///< Returns the existence status of the particle, i.e. whether it is confirmed by multiple experiments - std::string I() const { return m_isospin; } ///< Returns the isospin of the particle as a string. - std::string J() const { return m_JtotalSpin; } ///< Returns the total angular momentum of the particle + std::string I() const { return m_isospin; } ///< Returns the isospin of the particle as a string. + std::string J() const; std::string label() const { return m_texName; } ///< Returns the LaTeX formatted label for the particle std::string name() const; ///< Returns the particle name std::string spinName() const; ///< Returns the name of the particles spin. @@ -57,8 +57,8 @@ namespace AmpGen bool isNeutrino() const; ///< Check if the particle is a neutrino bool isPhoton() const; ///< Check if the particle is a photon - - const QuarkContent& netQuarkContent() const { return m_netQuarkContent; } ///< Returns the particle's quark content + void setProperty(const std::string& key, const std::string& value); ///< set a propery of a particle by key + const QuarkContent& quarkContent() const { return m_quarkContent; } ///< Returns the particle's quark content void setLabel( const std::string& label ) { m_texName = label; } ///< Set the LaTeX label of the particle void setName( const std::string& name ) { @@ -79,29 +79,28 @@ namespace AmpGen static const ParticleProperties* get( const std::string& name, const bool& quiet=false ); private: - double m_mass; ///< mass [GeV] - double m_mErrPlus; ///< +ve mass error [GeV] - double m_mErrMinus; ///< -ve mass error [GeV] - double m_width; ///< width [GeV] - double m_wErrPlus; ///< +ve width error [GeV] - double m_wErrMinus; ///< -ve width error [GeV] - double m_radius; ///< hadronic radius - int m_Gparity; ///< G-parity - int m_parity; ///< Parity - int m_Cparity; ///< Charge 'parity' - int m_pdgID; ///< PDG id - int m_Rexist; ///< likelihood of existence, baryons only - int m_charge; ///< electrical charge - int m_twoSpin; ///< twice the spin - std::string m_isospin; ///< isospin - std::string m_JtotalSpin; ///< total spin - std::string m_name; ///< particle name - std::string m_quarks; ///< quark string - std::string m_texName; ///< latex label of particle - std::string m_chargeString; ///< string for particle charge + double m_mass{0}; ///< mass [GeV] + double m_mErrPlus{0}; ///< +ve mass error [GeV] + double m_mErrMinus{0}; ///< -ve mass error [GeV] + double m_width{0}; ///< width [GeV] + double m_wErrPlus{0}; ///< +ve width error [GeV] + double m_wErrMinus{0}; ///< -ve width error [GeV] + double m_radius{0}; ///< hadronic radius + int m_Gparity{0}; ///< G-parity + int m_parity{0}; ///< Parity + int m_Cparity{0}; ///< Charge 'parity' + int m_pdgID{0}; ///< PDG id + int m_Rexist{0}; ///< likelihood of existence, baryons only + int m_charge{0}; ///< electrical charge + int m_twoSpin{0}; ///< twice the spin + std::string m_isospin{""}; ///< isospin + //std::string m_JtotalSpin{""}; ///< total spin + std::string m_name{""}; ///< particle name + std::string m_texName{""}; ///< latex label of particle + std::string m_chargeString{""}; ///< string for particle charge char m_Aformat; ///< anti-particle format character char m_status; ///< status (estalished or not etc) - QuarkContent m_netQuarkContent; ///< The quark content of the state (uD, uud etc.) + QuarkContent m_quarkContent; ///< The quark content of the state (uD, uud etc.) bool m_isValid; ///< Flag to check whether the ParticleProperties have configured correctly bool m_customName = {false}; ///< Flag to make custom name void antiQuarks(); diff --git a/AmpGen/ParticlePropertiesList.h b/AmpGen/ParticlePropertiesList.h index 43806094b46..289ccd8343d 100644 --- a/AmpGen/ParticlePropertiesList.h +++ b/AmpGen/ParticlePropertiesList.h @@ -48,6 +48,7 @@ namespace AmpGen void print( std::ostream& out = std::cout ) const; bool readLatexLabels( const std::string& name ); void makeMappings(); + void addParticle(const std::vector& properties ); }; std::ostream& operator<<( std::ostream& out, const ParticlePropertiesList& ppl ); } // namespace AmpGen diff --git a/apps/DataConverter.cpp b/apps/DataConverter.cpp index 2d8a2dc022c..23d84679183 100644 --- a/apps/DataConverter.cpp +++ b/apps/DataConverter.cpp @@ -208,14 +208,10 @@ int main( int argc, char* argv[] ) INFO("Closing file..."); outputFile->Close(); TFile* outputPlotFile = TFile::Open( plotsName.c_str(), "RECREATE" ); - auto plots = evts.makeDefaultProjections(); - auto proj = Projection([](auto& event){ return sqrt(event.s({0,1,2,3})) ; }, "m_D", "m_D",100, 1.8, 1.9 ); - for ( auto& plot : plots ) { - INFO( "Writing plot " << plot->GetName() << " to file" ); - plot->Write(); + auto projections = evtType.defaultProjections(); + for ( auto& p : projections ) { + p( evts ) -> Write(); + p( evts, WeightFunction([](auto& evt){ return 1; }), PlotOptions::Prefix("noweight") )->Write(); } - proj( evts )->Write(); - for( int i = 0 ;i != 4; ++i ) - Projection([i](auto& event){ return sqrt(event.s(i)) ; }, "m_"+std::to_string(i), "m_D",100, 0, 1.0 )(evts)->Write(); outputPlotFile->Close(); } diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 2139023116d..7a579ad0dac 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -60,7 +60,7 @@ CoherentSum::CoherentSum( const EventType& type, const MinuitParameterSet& mps, m_matrixElements[i] = TransitionMatrix(p, c, CompiledExpression( p.getExpression(m_dbThis ? &db : nullptr), p.decayDescriptor(), - this->m_evtType.getEventFormat(), db, this->m_mps ) ); + this->m_evtType.getEventFormat(), db, &mps ) ); CompilerWrapper().compile( m_matrixElements[i], this->m_objCache); } ); } diff --git a/src/EventList.cpp b/src/EventList.cpp index db09d143e5d..891537d84a8 100644 --- a/src/EventList.cpp +++ b/src/EventList.cpp @@ -124,8 +124,7 @@ void EventList::loadFromTree( TTree* tree, const ArgumentPack& args ) auto automaticOrdering = m_eventType.automaticOrdering(); for (const auto& evt : tr) { if( inputUnits != Units::GeV ) for( unsigned k = 0; k != eventFormat.size(); ++k ) temp[k] *= to_double(inputUnits); - // if( idBranches.size() != 0 && !automaticOrdering(temp, ids) ) - // WARNING("Failed to order event: " << evt ); + if( idBranches.size() != 0 && !automaticOrdering(temp, ids) ) WARNING("Failed to order event: " << evt ); if( applySym ) symmetriser(temp); if( ! hasEnergy ){ for( unsigned int k = 0 ; k != m_eventType.size(); ++k ) diff --git a/src/OptionsParser.cpp b/src/OptionsParser.cpp index 469794aed18..8702a80102d 100644 --- a/src/OptionsParser.cpp +++ b/src/OptionsParser.cpp @@ -12,6 +12,13 @@ using namespace AmpGen; OptionsParser* OptionsParser::gOptionsParser = nullptr; +OptionsParser::OptionsParser() +{ + m_keywords["Import"] = [this](const auto& tokens){ if( tokens.size() != 2 ) return; this->import(expandGlobals(tokens[1] ) ) ; }; + m_keywords["ParticleProperties"] = [](const auto& tokens){ ParticlePropertiesList::getMutable()->addParticle( tokens ); }; + m_keywords["ParticlePropertiesList::Alias"] = [](const auto& tokens){ if( tokens.size() !=3 ) return; ParticlePropertiesList::getMutable()->makeAlias( tokens[1], tokens[2] ); }; +} + OptionsParser* OptionsParser::getMe() { if( gOptionsParser == nullptr ) gOptionsParser = new OptionsParser(); @@ -25,9 +32,9 @@ void OptionsParser::setQuiet(){ bool OptionsParser::ignoreThisLine( const std::string& line ) { if ( line.empty() ) return true; - const char _ignoreLinesStartingWith[] = {'*', '#', '\0'}; - for ( int i = 0; _ignoreLinesStartingWith[i] != '\0'; i++ ) { - if ( line[0] == _ignoreLinesStartingWith[i] ) return true; + const char ignoreLinesStartingWith[] = {'*', '#', '\0'}; + for ( int i = 0; ignoreLinesStartingWith[i] != '\0'; i++ ) { + if ( line[0] == ignoreLinesStartingWith[i] ) return true; } return false; } @@ -55,9 +62,8 @@ void OptionsParser::setCommandLineArgs( int argc, char** argv, const std::string x++; } } - int depth = 0 ; if( key == "help" ) m_printHelp = true; - m_parsedLines[key] = makeParsedStrings( key + " " + val, depth ); + addArg(key +" " + val); } if( m_printHelp ){ std::cout << bold_on << "Usage: " << bold_off << argv[0] << italic_on << " options_file1.opt options_file2.opt --key1=value1 --key2=value2 ..." << italic_off << std::endl; @@ -80,40 +86,30 @@ void OptionsParser::import( const std::string& fName ) auto tokens = this->makeParsedStrings( line, braceDepth ); for ( auto& token : tokens ) currentTokens.push_back( token ); if ( tokens.size() == 0 ) return; - std::string name = currentTokens[0]; - if ( name == "Import" && currentTokens.size() == 2 ) { - this->import( expandGlobals( tokens[1] ) ); - currentTokens.clear(); - return; - } - if ( name == "ParticlePropertiesList::Alias" && currentTokens.size() == 3 ) { - ParticlePropertiesList::getMutable()->makeAlias( tokens[1], tokens[2] ); - currentTokens.clear(); - return; - } + std::string key = currentTokens[0]; if ( braceDepth != 0 ) return; - if ( this->m_parsedLines.find( name ) != this->m_parsedLines.end() ) { - WARNING( "Overwriting parameter: " << name ); + if ( this->m_parsedLines.find( key ) != this->m_parsedLines.end() ) { + WARNING( "Overwriting parameter: " << key ); } - currentTokens.erase( std::remove_if( currentTokens.begin(), currentTokens.end(), - []( const std::string& o ) { return o == "{" || o == "}"; } ), - currentTokens.end() ); - this->m_parsedLines[name] = currentTokens; + auto isCurlyBrace = []( const std::string& o ) { return o == "{" || o == "}"; }; + currentTokens.erase( std::remove_if( currentTokens.begin(), currentTokens.end(), isCurlyBrace), currentTokens.end() ); + this->addArg( currentTokens ); currentTokens.clear(); } ); - - } void OptionsParser::addArg( const std::string& arg ) { int bc = 0 ; - auto tokens = makeParsedStrings( arg, bc ); - auto name = tokens[0]; - if ( name == "ParticlePropertiesList::Alias" && tokens.size() == 3 ) { - ParticlePropertiesList::getMutable()->makeAlias( tokens[1], tokens[2] ); - } - m_parsedLines[name] = tokens; + addArg( makeParsedStrings( arg, bc ) ); +} + +void OptionsParser::addArg( const std::vector& tokens ) +{ + auto& key = tokens[0]; + DEBUG("Adding arg with key: " << key ); + if( m_keywords.count(key) != 0 ) m_keywords[key]( tokens ); + else m_parsedLines[key] = tokens; } std::vector OptionsParser::makeParsedStrings( const std::string& line, int& braceDepth ) const diff --git a/src/Particle.cpp b/src/Particle.cpp index 784011c2748..00e31034e6f 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -162,12 +162,11 @@ void Particle::pdgLookup() } else m_usesDefaultLineshape = false; m_parity = m_props->P(); - if ( !isdigit( m_props->J()[0] ) ) ERROR( "Spin not recognised! : " << m_name << " J = " << m_props->J() ); + // if ( !isdigit( m_props->J()[0] ) ) ERROR( "Spin not recognised! : " << m_name << " J = " << m_props->J() ); if( m_defaultModifier != "" && m_lineshape.find(".") == std::string::npos ){ m_lineshape = m_lineshape + "." + m_defaultModifier.getVal(); } bool isStrong = quarks() == daughterQuarks(); - DEBUG( m_name << " is decaying via " << ( isStrong ? "strong" : "electroweak" ) << " interactions; P = " << props()->P() ); if ( m_name.find( "NonRes" ) != std::string::npos ) isStrong = true; m_minL = m_daughters.size() == 2 ? orbitalRange( isStrong ).first : 0; if ( m_daughters.size() == 2 ) { @@ -176,6 +175,9 @@ void Particle::pdgLookup() << " d1 = " << m_daughters[1]->name() ); } if ( m_orbital == 0 ) m_orbital = m_minL; // define in ground state unless specified + if( m_daughters.size() != 0 ){ + DEBUG( m_name << " is decaying via " << ( isStrong ? "strong" : "electroweak" ) << " interactions; P = " << props()->P() << "l = " << m_orbital ); + } int charge = 0; for ( auto& d : m_daughters ){ d->setParent(this); @@ -642,7 +644,7 @@ Particle Particle::conj( bool invertHead , bool reorder ) QuarkContent Particle::quarks() const { - return m_name.find("NonRes") != std::string::npos ? daughterQuarks() : m_props->netQuarkContent(); + return m_name.find("NonRes") != std::string::npos ? daughterQuarks() : m_props->quarkContent(); } QuarkContent Particle::daughterQuarks() const diff --git a/src/ParticleProperties.cpp b/src/ParticleProperties.cpp index e9e512fe95e..a3471531777 100644 --- a/src/ParticleProperties.cpp +++ b/src/ParticleProperties.cpp @@ -19,7 +19,7 @@ void ParticleProperties::print( std::ostream& out ) const out << "Mass " << mass() << " +" << mErrPlus() << " -" << mErrMinus() << "\nWidth " << width() << " +" << wErrPlus() << " -" << wErrMinus() << "\n I=" << I() << ", G=" << G() << "\n J=" << J() << ", C=" << C() << ", P=" << P() << "\n Q = " << charge() << "\n pdgID " << pdgID() << "\n name " << name() - << "\n net-quark-content " << netQuarkContent() << "\n is its own antiparticle? " + << "\n quark-content " << quarkContent() << "\n is its own antiparticle? " << ( hasDistinctAnti() ? "no" : "yes" ) << "\n radius " << radius() * GeV << " /GeV" << "\n"; } @@ -36,7 +36,15 @@ int ParticleProperties::chargeFromString( const std::string& ch, bool& status ) return 0; } -ParticleProperties::ParticleProperties( const std::string& pdg_string ) : m_netQuarkContent() +std::string ParticleProperties::J() const +{ + if( m_twoSpin == -1 ) return "?"; + if( m_twoSpin % 2 == 0 ) return std::to_string( int(m_twoSpin/2) ); + if( m_twoSpin % 2 == 1 ) return std::to_string( int(m_twoSpin/2) ) + "/2"; + return ""; +} + +ParticleProperties::ParticleProperties( const std::string& pdg_string ) { m_isValid = false; if ( pdg_string == "" || pdg_string.empty() ) return; @@ -61,21 +69,19 @@ ParticleProperties::ParticleProperties( const std::string& pdg_string ) : m_netQ m_Cparity = chargeFromString( s[10], status ); m_charge = chargeFromString( s[13], status ); m_isospin = s[6]; - m_JtotalSpin = s[8]; m_status = s[15][0]; m_name = s[16]; - m_quarks = s[17]; m_Aformat = s[11].size() == 1 ? s[11][0] : ' '; m_chargeString = s[13]; - m_netQuarkContent = QuarkContent( m_quarks ); + m_quarkContent = QuarkContent( s[17] ); bool spin_status = 1; - if( m_JtotalSpin == "?" ) m_twoSpin = 0; - else if( m_JtotalSpin.find("/") != std::string::npos ){ - m_twoSpin = lexical_cast( m_JtotalSpin.substr(0, m_JtotalSpin.find("/") ) , spin_status ); + if( s[8] == "?" ) m_twoSpin = -1; + else if( s[8].find("/") != std::string::npos ){ + m_twoSpin = lexical_cast( s[8].substr(0, s[8].find("/") ) , spin_status ); } - else m_twoSpin = 2 * lexical_cast( m_JtotalSpin, spin_status ); + else m_twoSpin = 2 * lexical_cast( s[8], spin_status ); if( spin_status == 0 ){ - DEBUG("Spin of particle: " << name() << " could not be interpretted (J=" << m_JtotalSpin << ")" ); + DEBUG("Spin of particle: " << name() << " could not be interpretted (J=" << s[8] << ")" ); } m_radius = 1.5 / GeV; bool isCharm = ( abs(pdgID()) == 421 || @@ -94,6 +100,7 @@ bool ParticleProperties::antiThis() swapChars( m_chargeString, '+', '-'); m_charge *= -1; if( isFermion() ) m_parity *= -1; + /* if ( !m_quarks.empty() ){ swapChars(m_quarks, 'U', 'u'); swapChars(m_quarks, 'D', 'd'); @@ -106,7 +113,8 @@ bool ParticleProperties::antiThis() m_quarks.replace( pos, 4, "sqrt" ); } } - m_netQuarkContent.antiThis(); + */ + m_quarkContent.antiThis(); m_pdgID *= -1; return true; } @@ -176,7 +184,7 @@ std::string ParticleProperties::spinName() const { if( m_twoSpin == 5 ) return "e"; if( m_twoSpin == 7 ) return "c"; } - WARNING("Spin name not implemented for " << m_JtotalSpin ); + WARNING("Spin name not implemented for " << m_twoSpin ); return "?"; } @@ -205,3 +213,30 @@ bool ParticleProperties::operator>( const ParticleProperties& rhs ) const { retu bool ParticleProperties::operator<=( const ParticleProperties& rhs ) const { return ( *this < rhs || *this == rhs ); } bool ParticleProperties::operator>=( const ParticleProperties& rhs ) const { return ( *this > rhs || *this == rhs ); } + +void ParticleProperties::setProperty(const std::string& key, const std::string& value) +{ + DEBUG("Setting property: " << key << " " << value ); + bool status = true; + if( key == "mass" ) m_mass = stod(value) / MeV; + else if( key == "name" ) m_name = value; + else if( key == "width" ) m_width = stod(value) / MeV; + else if( key == "spin" ) + { + bool spin_status = 1; + if( value == "?" ) m_twoSpin = 0; + else if( value.find("/") != std::string::npos ){ + m_twoSpin = lexical_cast( value.substr(0, value.find("/") ) , spin_status ); + } + else m_twoSpin = 2 * lexical_cast( value, spin_status ); + if( spin_status == 0 ){ + ERROR("Spin of particle: " << name() << " could not be interpretted (J=" << value << ")" ); + } + } + else if( key == "parity" ) m_parity = chargeFromString( value, status ); + else if( key == "charge" ) m_charge = chargeFromString( value, status ); + else if( key == "quarks" ) m_quarkContent = QuarkContent(value); + else { + ERROR("Unrecognised key: " << key ); + } +} diff --git a/src/ParticlePropertiesList.cpp b/src/ParticlePropertiesList.cpp index 9745d94f59d..95c9d6877fc 100644 --- a/src/ParticlePropertiesList.cpp +++ b/src/ParticlePropertiesList.cpp @@ -202,4 +202,26 @@ void ParticlePropertiesList::makeAlias( const std::string& name, const std::stri m_byName[alias] = pp; } +void ParticlePropertiesList::addParticle( const std::vector& tokens ) +{ + INFO( vectorToString(tokens, " ") ); + auto name = tokens[1]; + if( tokens.size() % 2 != 0 ) ERROR("Expecting properties as set of key value pairs"); + ParticleProperties* pp = nullptr; + if( m_byName.find( name ) != m_byName.end() ) + { + WARNING("Overwriting properties of existing particle"); + pp = m_byName[name]; + } + else { + pp = new ParticleProperties(); + pp->setProperty("name", name ); + } + for( int i = 2; i != tokens.size(); i+=2 ) + { + pp->setProperty( tokens[i], tokens[i+1] ); + } + m_byName[name] = pp; +} + double ParticlePropertiesList::quasiStableThreshold() const { return m_quasiStableThreshold; } diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 1db1caeb531..3e9febabcef 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -61,35 +61,34 @@ PolarisedSum::PolarisedSum(const EventType& type, { std::string objCache = NamedParameter("PolarisedSum::ObjectCache", "" ); spaceType stype = NamedParameter( "PolarisedSum::SpaceType" , spaceType::spin); + ThreadPool tp(std::thread::hardware_concurrency() ); if( stype == spaceType::spin ) { auto prodPols = polarisations(m_eventType.mother()); std::vector> polStates; for(const auto& pol : prodPols ) polStates.push_back({pol}); - for(unsigned i = 0 ; i != type.size(); ++i ) polStates = indexProduct(polStates, polarisations( type[i] ) ); - + for(unsigned i = 0 ; i != type.size(); ++i ) polStates = indexProduct(polStates, polarisations( type[i] ) ); auto protoAmps = m_rules.getMatchingRules(m_eventType); for(const auto& m : protoAmps ) INFO( m.first.uniqueString() ); m_matrixElements.resize( protoAmps.size() ); - ThreadPool tp(std::thread::hardware_concurrency() ); for(unsigned i = 0; i < m_matrixElements.size(); ++i) { - tp.enqueue( [i, &protoAmps, &polStates, this]{ - Tensor thisExpression( Tensor::dim(polStates.size()) ); - auto& [p, coupling] = protoAmps[i]; - DebugSymbols syms; - for(unsigned j = 0; j != polStates.size(); ++j) thisExpression[j] = make_cse( p.getExpression(j == 0 ? &syms: nullptr, polStates[j] ) ); - m_matrixElements[i] = TransitionMatrix( - p, - coupling, - CompiledExpression( - TensorExpression(thisExpression), - p.decayDescriptor(), - this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,this->m_mps ) ); + auto [p, c] = protoAmps[i]; + tp.enqueue( [i, p, c, polStates, &mps, this] () mutable { + Tensor thisExpression( Tensor::dim(polStates.size()) ); + DebugSymbols syms; + for(unsigned j = 0; j != polStates.size(); ++j) + thisExpression[j] = make_cse( p.getExpression(j == 0 ? &syms: nullptr, polStates[j] ) ); + + this->m_matrixElements[i] = TransitionMatrix( + p, c, + CompiledExpression( + TensorExpression(thisExpression), p.decayDescriptor(), &mps, + this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ) ); + CompilerWrapper().compile( m_matrixElements[i] ); - m_matrixElements[i].size = thisExpression.size(); - } - ); + m_matrixElements[i].size = thisExpression.size(); + }); } } if ( stype == spaceType::flavour ) @@ -98,24 +97,21 @@ PolarisedSum::PolarisedSum(const EventType& type, auto r1 = m_rules.getMatchingRules(m_eventType, m_prefix); auto r2 = m_rules.getMatchingRules(m_eventType.conj(true), m_prefix); m_matrixElements.resize( r1.size() + r2.size() ); - ThreadPool tp(8); for(unsigned i = 0 ; i != m_matrixElements.size(); ++i) { - tp.enqueue( [i, this, &r1, &r2]{ - Tensor thisExpression( Tensor::dim(2) ); - DebugSymbols syms; - auto& tm = i < r1.size() ? r1[i] : r2[i-r1.size()]; - thisExpression[0] = i < r1.size() ? make_cse( tm.first.getExpression(&syms) ) : 0; - thisExpression[1] = i < r1.size() ? 0 : make_cse( tm.first.getExpression(&syms) ); - m_matrixElements[i] = TransitionMatrix( - tm.first, - tm.second, - CompiledExpression( - TensorExpression(thisExpression), - tm.first.decayDescriptor(), - this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ,this->m_mps ) ); - CompilerWrapper().compile( m_matrixElements[i] ); - }); + tp.enqueue( [i, this, &r1, &r2] () mutable { + Tensor thisExpression( Tensor::dim(2) ); + DebugSymbols syms; + auto& [p,coupling] = i < r1.size() ? r1[i] : r2[i-r1.size()]; + thisExpression[0] = i < r1.size() ? make_cse( p.getExpression(&syms) ) : 0; + thisExpression[1] = i < r1.size() ? 0 : make_cse( p.getExpression(&syms) ); + this->m_matrixElements[i] = TransitionMatrix( + p, coupling, + CompiledExpression( + TensorExpression(thisExpression), p.decayDescriptor(), this->m_mps, + this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ) ); + CompilerWrapper().compile( m_matrixElements[i] ); + }); } } if( m_pVector.size() == 0 ) @@ -129,7 +125,7 @@ PolarisedSum::PolarisedSum(const EventType& type, DebugSymbols db; auto prob = probExpression(transitionMatrix(), convertProxies(m_pVector,[](auto& p){ return Parameter(p->name());} ), m_debug ? &db : nullptr); - m_probExpression = make_expression( prob, "prob_unnormalised", *m_mps ); + m_probExpression = make_expression( prob, "prob_unnormalised", m_mps ); } std::vector PolarisedSum::polarisations( const std::string& name ) const @@ -363,14 +359,14 @@ void PolarisedSum::generateSourceCode(const std::string& fname, const double& no auto amp_extPol = probExpression(T_matrix, {Parameter("x2",0,true), Parameter("x3",0,true), Parameter("x4",0,true)}); stream << CompiledExpression( amp / normalisation, "FCN",{},{}, m_mps ) << std::endl ; + const int&)>( amp / normalisation, "FCN", m_mps, disableBatch() ) << std::endl ; stream << CompiledExpression( amp_extPol / normalisation, "FCN_extPol",{},{},m_mps ) << std::endl; + const double&)>(amp_extPol / normalisation, "FCN_extPol", m_mps, disableBatch() ) << std::endl; stream.close(); } diff --git a/src/ThreeBodyCalculators.cpp b/src/ThreeBodyCalculators.cpp index d6351163d76..20c9eb69447 100644 --- a/src/ThreeBodyCalculators.cpp +++ b/src/ThreeBodyCalculators.cpp @@ -240,9 +240,9 @@ ThreeBodyCalculator::PartialWidth::PartialWidth( const EventType& evt, MinuitPar auto evtFormat = evt.getEventFormat(); for ( auto& p : unpacked ) { name += p.first.decayDescriptor(); - partialWidths.emplace_back( spinAverageMatrixElement( {p}, &msym ), p.first.decayDescriptor(), evtFormat, DebugSymbols(), &mps ); + partialWidths.emplace_back( spinAverageMatrixElement( {p}, &msym ), p.first.decayDescriptor(), &mps, evtFormat); } - totalWidth = CompiledExpression< complex_t(const real_t*, const real_t*) > ( matrixElementTotal, "width", evtFormat, {} , &mps ); + totalWidth = CompiledExpression< complex_t(const real_t*, const real_t*) > ( matrixElementTotal, "width", &mps, evtFormat); CompilerWrapper(true).compile( totalWidth, ""); } From 9a16468951b64a47f057ca71471ff1c9d1c21f90 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 8 Jun 2020 13:06:53 +0200 Subject: [PATCH 207/250] fix polarisedSum issue for clang --- src/PolarisedSum.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 3e9febabcef..b5e582ea8b0 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -73,8 +73,8 @@ PolarisedSum::PolarisedSum(const EventType& type, m_matrixElements.resize( protoAmps.size() ); for(unsigned i = 0; i < m_matrixElements.size(); ++i) { - auto [p, c] = protoAmps[i]; - tp.enqueue( [i, p, c, polStates, &mps, this] () mutable { + auto [lp, lc] = protoAmps[i]; + tp.enqueue( [i, p=lp, c=lc, polStates, &mps, this] () mutable { Tensor thisExpression( Tensor::dim(polStates.size()) ); DebugSymbols syms; for(unsigned j = 0; j != polStates.size(); ++j) From 614a5a1cdead60815ed19bc25165ddaf0443f8e7 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 9 Jun 2020 11:58:07 +0200 Subject: [PATCH 208/250] fix isPhoton flag --- AmpGen/Generator.h | 1 + AmpGen/ParticleProperties.h | 1 - src/CoherentSum.cpp | 4 +++- src/ParticleProperties.cpp | 2 +- src/TreePhaseSpace.cpp | 19 ++++++++++++------- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/AmpGen/Generator.h b/AmpGen/Generator.h index b864c166d1e..5fafd74a841 100644 --- a/AmpGen/Generator.h +++ b/AmpGen/Generator.h @@ -109,6 +109,7 @@ namespace AmpGen if ( event.genPdf() > maxProb ) { std::cout << std::endl; WARNING( "PDF value exceeds norm value: " << event.genPdf() << " > " << maxProb ); +// pdf.debug( event ); } if ( accept_all || event.genPdf() > maxProb * m_rnd->Rndm() ){ list.push_back(event); diff --git a/AmpGen/ParticleProperties.h b/AmpGen/ParticleProperties.h index 74adeab6dd3..df8e000bfe3 100644 --- a/AmpGen/ParticleProperties.h +++ b/AmpGen/ParticleProperties.h @@ -94,7 +94,6 @@ namespace AmpGen int m_charge{0}; ///< electrical charge int m_twoSpin{0}; ///< twice the spin std::string m_isospin{""}; ///< isospin - //std::string m_JtotalSpin{""}; ///< total spin std::string m_name{""}; ///< particle name std::string m_texName{""}; ///< latex label of particle std::string m_chargeString{""}; ///< string for particle charge diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 7a579ad0dac..980e224e060 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -112,6 +112,8 @@ void CoherentSum::updateNorms() void CoherentSum::debug( const Event& evt, const std::string& nameMustContain ) { prepare(); + INFO("Weight = " << evt.weight() << " genPDF = " << evt.genPdf() ); + for ( auto& me : m_matrixElements ) { auto A = me(evt); INFO( std::setw(70) << me.decayTree.uniqueString() @@ -120,7 +122,7 @@ void CoherentSum::debug( const Event& evt, const std::string& nameMustContain ) << m_cache( evt.index(), std::distance(&m_matrixElements[0], &me ) ) << me.decayTree.CP() ); } - if( m_dbThis ) for ( auto& me : m_matrixElements ) me.debug( m_events->block(0) ); + if( m_dbThis ) for ( auto& me : m_matrixElements ) me.debug( evt) ; INFO( "A(x) = " << getVal(evt) << " without cache: " << getValNoCache(evt) ); } diff --git a/src/ParticleProperties.cpp b/src/ParticleProperties.cpp index a3471531777..bba59dd93d7 100644 --- a/src/ParticleProperties.cpp +++ b/src/ParticleProperties.cpp @@ -153,7 +153,7 @@ bool ParticleProperties::isFermion() const { bool ParticleProperties::isPhoton() const { - return m_name == "gamma0"; + return m_pdgID == 22; } bool ParticleProperties::isNeutrino() const diff --git a/src/TreePhaseSpace.cpp b/src/TreePhaseSpace.cpp index d7cf82ec4f5..e1447a1ea16 100644 --- a/src/TreePhaseSpace.cpp +++ b/src/TreePhaseSpace.cpp @@ -50,13 +50,18 @@ TreePhaseSpace::TreePhaseSpace(const std::vector& decayChains, const E Event TreePhaseSpace::makeEvent() { - unsigned j = m_dice(m_gen); - // INFO("Producing event from tree: " << j ); - if( j >= m_top.size() ) ERROR("Out of bounds: " << j << " / " << m_top.size() ); - m_top[j].generate(); - auto event = m_top[j].event(m_type.size()); - double w = m_top[j].weight(); - event.setGenPdf( w == 0 ? 0 : genPdf(event) / w ); + unsigned j = 0; + double w = 0; + Event event; + do { + // INFO("Producing event from tree: " << j ); + j = m_dice(m_gen); + if( j >= m_top.size() ) ERROR("Out of bounds: " << j << " / " << m_top.size() ); + m_top[j].generate(); + event = m_top[j].event(m_type.size()); + w = m_top[j].weight(); + event.setGenPdf( w == 0 ? 0 : genPdf(event) / w ); + } while ( w == 0 ); m_generatorRecord.push_back(j); return event; } From b4863e3abfa931d613907685eda4603ecd59f43d Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 9 Jun 2020 13:17:54 +0200 Subject: [PATCH 209/250] add some sanity checks for photons --- src/PolarisedSum.cpp | 11 +++++------ src/Wigner.cpp | 11 +++++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index b5e582ea8b0..5994eb171c3 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -131,12 +131,11 @@ PolarisedSum::PolarisedSum(const EventType& type, std::vector PolarisedSum::polarisations( const std::string& name ) const { auto props = *ParticlePropertiesList::get( name ); - if( props.twoSpin() == 0 ) return {0}; - if( props.twoSpin() == 1 ) return {1,-1}; - if( props.twoSpin() == 4 ) return {-2,1,0,1,2}; - if( name == "gamma0" && props.twoSpin() == 2 ) return {1,-1}; - if( name != "gamma0" && props.twoSpin() == 2 ) return {1,0,-1}; - + if( props.twoSpin() == 0 ) return {0}; // scalar + if( props.isPhoton() ) return {1,-1}; // photon + if( props.twoSpin() == 1 ) return {1,-1}; // fermion + if( props.twoSpin() == 4 ) return {-2,1,0,1,2};// tensor + if( props.twoSpin() == 2 ) return {1,0,-1}; // vector else { WARNING("Particle with spin: " << props.twoSpin() << "/2" << " not implemented in initial/final state"); return {0}; diff --git a/src/Wigner.cpp b/src/Wigner.cpp index e098175b9c6..9a676900334 100644 --- a/src/Wigner.cpp +++ b/src/Wigner.cpp @@ -130,7 +130,8 @@ std::pair angCoordinates(const Tensor& P, DebugSymbols* Expression px = P[0] / sqrt(pt2); Expression py = P[1] / sqrt(pt2); return {pz, make_cse(px + 1i*py)}; -} +} /// spherical coordinates are paramterised as {z=cos(theta), e^(iphi)}, as this avoids any trigonometric functions + Expression AmpGen::wigner_D(const std::pair& P, const double& J, const double& lA, @@ -249,6 +250,8 @@ Expression AmpGen::helicityAmplitude(const Particle& particle, { if( particle.props()->twoSpin() == 0 ) return Mz==0; // a scalar // polarisation spinor / vector etc. in the quantisation of the lab (i.e. along the z-axis or lab particle momentum) + if( particle.props()->isPhoton() && Mz == 0. ) ERROR("Photon polarisation state is wrong"); + if( particle.polState() == 0 ) ERROR("Photon external state is wrong..."); auto labPol = particle.externalSpinTensor(particle.polState(), db); auto inverseMyTransform = myFrame.inverse(); if( particle.props()->twoSpin() == 1 ) // so a fermion @@ -291,12 +294,12 @@ Expression AmpGen::helicityAmplitude(const Particle& particle, } Expression total = 0; - std::pair hco = angCoordinates( myFrame(d1.P()) , db); + auto hco = angCoordinates( myFrame(d1.P()) , db); for( auto& coupling : recoupling_constants ) { auto dm = coupling.m1 - coupling.m2; - if( (d1.name() == "gamma0" && coupling.m1 == 0) || - (d2.name() == "gamma0" && coupling.m2 == 0) ) continue; + if( (d1.props()->isPhoton() && coupling.m1 == 0.) || + (d2.props()->isPhoton() && coupling.m2 == 0.) ) continue; auto term = wigner_D(hco, particle.spin(), Mz, dm, db); auto h1 = helicityAmplitude(d1, myFrame, coupling.m1, db, +1, cachePtr); auto h2 = helicityAmplitude(d2, myFrame, coupling.m2, db, -1, cachePtr); From d5e981b0bfb65f750b10d3e5c33f60d3127950f2 Mon Sep 17 00:00:00 2001 From: Timothy David Evans Date: Mon, 29 Jun 2020 09:09:57 +0200 Subject: [PATCH 210/250] fix cuts in DataConvertor --- Standalone.cmake | 2 +- apps/DataConverter.cpp | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Standalone.cmake b/Standalone.cmake index c2284d0e92e..9dc1819d549 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -222,7 +222,7 @@ add_subdirectory(test) include(CMakePackageConfigHelpers) write_basic_package_version_file(AmpGenVersion.cmake VERSION ${PACKAGE_VERSION} COMPATIBILITY AnyNewerVersion) -configure_file(AmpGenConfig.cmake.in AmpGenConfig.cmake) # @ONLY) +configure_file(AmpGenConfig.cmake.in AmpGenConfig.cmake) export( TARGETS AmpGen NAMESPACE AmpGen:: FILE AmpGenTargets.cmake ) set(CMAKE_EXPORT_PACKAGE_REGISTRY ON) diff --git a/apps/DataConverter.cpp b/apps/DataConverter.cpp index 23d84679183..8a41a628a0e 100644 --- a/apps/DataConverter.cpp +++ b/apps/DataConverter.cpp @@ -52,7 +52,7 @@ int main( int argc, char* argv[] ) std::vector idBranches = NamedParameter("IdBranches" , std::vector() ).getVector(); bool usePIDCalib = NamedParameter("usePIDCalib" , false); bool rejectMultipleCandidates = NamedParameter("rejectMultipleCandidates", true ); - std::string cuts = NamedParameter("Cut",""); + auto cuts = NamedParameter("Cut","").getVector(); EventType evtType( NamedParameter( "EventType" ).getVector() ); std::vector branches; @@ -70,7 +70,6 @@ int main( int argc, char* argv[] ) in_tree->AddFriend( tokens[1].c_str(), tokens[0].c_str() ); } - INFO( "Using cut = " << cuts ); if(inputFilename == "") FATAL("No input specified in options" ); if(treeName == "") FATAL("No tree specified in options" ); @@ -79,8 +78,11 @@ int main( int argc, char* argv[] ) if(in_tree == nullptr ) FATAL(treeName + " not found" ); INFO( "Got tree " << inputFilename << ":" << treeName ); - - in_tree->Draw( ">>elist", cuts.c_str() ); + std::string cut = ""; + for( auto& i : cuts ) cut += i; + INFO( "Using cut = " << cut ); + + in_tree->Draw( ">>elist", cut.c_str() ); TEventList* elist = (TEventList*)gDirectory->Get( "elist" ); INFO( "Total efficiency = " << elist->GetN() / (double)in_tree->GetEntries() ); @@ -187,14 +189,9 @@ int main( int argc, char* argv[] ) } if ( pdfLibrary != "" ) { INFO( "Setting generator level PDF from " << pdfLibrary ); - void* handle = dlopen( pdfLibrary.c_str(), RTLD_NOW ); - if ( handle == nullptr ) dlerror(); - - DynamicFCN fcn( handle, "FCN" ); + DynamicFCN fcn( pdfLibrary, "FCN" ); for ( unsigned int i = 0; i < evts.size(); ++i ) { - if ( i % 500000 == 0 ) { - INFO( "Set for " << i << " events" ); - } + if ( i % 500000 == 0 ) INFO( "Set for " << i << " events" ); evts[i].setGenPdf( fcn( (const real_t*)(evts[i]), 1 ) ); } } @@ -211,7 +208,12 @@ int main( int argc, char* argv[] ) auto projections = evtType.defaultProjections(); for ( auto& p : projections ) { p( evts ) -> Write(); - p( evts, WeightFunction([](auto& evt){ return 1; }), PlotOptions::Prefix("noweight") )->Write(); + // p( evts, WeightFunction([](auto& evt){ return 1; }), PlotOptions::Prefix("noweight") )->Write(); + } + for( int i = 0 ; i != evtType.size(); ++i ) + { + Projection p( [i](auto& event){ return sqrt( event.s(i) ); }, "m_"+std::to_string(i), "m_"+std::to_string(i), 100, 0, 2.5 ); + p(evts)->Write(); } outputPlotFile->Close(); } From e527eb0db399328532ed8c7af4450e310f292bcb Mon Sep 17 00:00:00 2001 From: Timothy David Evans Date: Mon, 27 Jul 2020 14:54:24 +0200 Subject: [PATCH 211/250] Fix complex logarithm for AVX, Weyl spinors for neutrinos --- AmpGen/DiracMatrices.h | 1 + AmpGen/PolarisedSum.h | 2 +- AmpGen/simd/avx2d_types.h | 8 ++++++-- AmpGen/simd/avx2f_types.h | 5 +++-- apps/Debugger.cpp | 4 +++- apps/Generator.cpp | 19 ++++++++++++++---- src/DiracMatrices.cpp | 14 +++++++++++++ src/Particle.cpp | 26 ++++++++++++------------- src/PolarisedSum.cpp | 36 +++++++++++++++++++++------------- src/Spline.cpp | 2 +- src/Tensor.cpp | 3 --- src/Vertex.cpp | 4 ++++ test/test_avx2d.cpp | 41 ++++++++++++++------------------------- 13 files changed, 99 insertions(+), 66 deletions(-) diff --git a/AmpGen/DiracMatrices.h b/AmpGen/DiracMatrices.h index 4ccd1330830..7e646e323b4 100644 --- a/AmpGen/DiracMatrices.h +++ b/AmpGen/DiracMatrices.h @@ -12,6 +12,7 @@ namespace AmpGen extern const Expression Z; extern const std::array Gamma; extern const std::array Sigma; + extern const std::array Sigma4; extern const std::array S03; extern const std::array SU3; } // namespace AmpGen diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index 987a090dd6d..70221e910e0 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -69,7 +69,7 @@ namespace AmpGen std::vector fitFractions(const LinearErrorPropagator&); std::vector> matrixElements() const; void transferParameters(); - Tensor transitionMatrix(); + Tensor transitionMatrix() const; const TransitionMatrix& operator[](const size_t& i) const { return m_matrixElements[i] ; } std::function evaluator(const EventList_type* = nullptr) const; KeyedFunctors componentEvaluator(const EventList_type* = nullptr) const; diff --git a/AmpGen/simd/avx2d_types.h b/AmpGen/simd/avx2d_types.h index 0e07026d45c..c232663eaee 100644 --- a/AmpGen/simd/avx2d_types.h +++ b/AmpGen/simd/avx2d_types.h @@ -33,7 +33,7 @@ namespace AmpGen { real_v(const double& f ) : data( _mm256_set1_pd( f )) {} real_v(const double& x0, const double& x1, const double& x2, const double& x3 ) { - data = _mm256_set_pd(x0,x1,x2,x3); + data = _mm256_set_pd(x3,x2,x1,x0); } real_v(const double* f ) : data( _mm256_loadu_pd( f ) ) {} real_v(const std::array f ) : data( _mm256_loadu_pd( f.data() ) ) {} @@ -67,6 +67,7 @@ namespace AmpGen { libmvec_alias( cos ) libmvec_alias( exp ) libmvec_alias( log ) + //inline real_v log( const real_v& v ){ auto arr = v.to_array(); return real_v( std::log(arr[0]), std::log(arr[1]), std::log(arr[2]), std::log(arr[3])) ; } inline void sincos( const real_v& v, real_v& s, real_v& c ) { #if USE_MVEC @@ -138,6 +139,9 @@ namespace AmpGen { complex_v( const float& re, const float& im) : re(re), im(im) {} complex_v( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} complex_v( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} + complex_v( const std::complex* arr ) : + re ( arr[0].real(), arr[1].real(), arr[2].real(), arr[3].real() ), + im ( arr[0].imag(), arr[1].imag(), arr[2].imag(), arr[3].imag() ){} explicit complex_v( const real_v& arg ) : re(arg) {}; explicit complex_v( const double& arg ) : re(arg) {}; const std::complex at(const unsigned i) const { return std::complex(re.to_array()[i], im.to_array()[i]) ; } @@ -194,7 +198,7 @@ namespace AmpGen { } inline complex_v log( const complex_v& v ) { - return complex_v( log( v.re ) , atan2(v.im, v.re) ); + return complex_v( 0.5 * log( v.norm() ) , atan2(v.im, v.re) ); } inline std::ostream& operator<<( std::ostream& os, const complex_v& obj ) { return os << "( "<< obj.re << ") (" << obj.im << ")"; } diff --git a/AmpGen/simd/avx2f_types.h b/AmpGen/simd/avx2f_types.h index 096f2058cdc..d5fc784b3ba 100644 --- a/AmpGen/simd/avx2f_types.h +++ b/AmpGen/simd/avx2f_types.h @@ -36,7 +36,7 @@ namespace AmpGen { real_v(const float& x0, const float& x1, const float& x2, const float& x3, const float& x4, const float& x5, const float& x6, const float& x7) { - data = _mm256_set_ps(x0,x1,x2,x3,x4,x5,x6,x7); + data = _mm256_set_ps(x7,x6,x5,x4,x3,x2,x1,x0); } void store( float* ptr ) const { _mm256_storeu_ps( ptr, data ); } @@ -138,6 +138,7 @@ namespace AmpGen { complex_v( const float& re, const float& im) : re(re), im(im) {} complex_v( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} complex_v( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} + const std::complex at(const unsigned i) const { return std::complex(re.to_array()[i], im.to_array()[i]) ; } void store( float* sre, float* sim ) const { re.store(sre); im.store(sim); } void store( std::complex* r ) const { @@ -187,7 +188,7 @@ namespace AmpGen { } inline complex_v log( const complex_v& v ) { - return complex_v( log( v.re ) , atan2(v.im, v.re) ); + return complex_v( 0.5 * log( v.norm() ) , atan2(v.im, v.re) ); } inline std::ostream& operator<<( std::ostream& os, const complex_v& obj ) { return os << "( "<< obj.re << ") (" << obj.im << ")"; } #pragma omp declare reduction(+: real_v: \ diff --git a/apps/Debugger.cpp b/apps/Debugger.cpp index 98308235d4a..35f65cccd0e 100644 --- a/apps/Debugger.cpp +++ b/apps/Debugger.cpp @@ -55,9 +55,11 @@ template < class FCN > void debug( FCN& sig, EventList& accepted, bool verbose, sig.debug( accepted[eventToDebug] ); accepted[eventToDebug].print(); // if( verbose ) print( accepted[0], sig.matrixElements(), verbose ); - invertParity(accepted[eventToDebug], accepted.eventType().size() ); + for( unsigned int i = 0 ; i != accepted.size(); ++i ) + invertParity(accepted[i], accepted.eventType().size() ); accepted[eventToDebug].print(); sig.reset(); + sig.setEvents(accepted); sig.prepare(); sig.debug( accepted[eventToDebug] ); } diff --git a/apps/Generator.cpp b/apps/Generator.cpp index 1bc01fe1a8b..612cbfed422 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -53,6 +53,7 @@ struct FixedLibPDF void debug( const Event& event) {}; void prepare(){}; void setEvents( AmpGen::EventList& evts ){}; + void setEvents( AmpGen::EventListSIMD& evts ){}; double operator()( const AmpGen::Event& evt ) const { return PDF( evt, 1 ); } double operator()( const double* evt, const unsigned& index ) { @@ -99,6 +100,14 @@ template void generateEvents( EventList& events , TRandom* rndm , const bool& normalise = true ) { + if constexpr( std::is_same::value ) + { + Generator signalGenerator(events.eventType(), rndm); + signalGenerator.setBlockSize(blockSize); + signalGenerator.setNormFlag(normalise); + signalGenerator.fillEventList(pdf, events, nEvents ); + } + else { if( phsp_type == phspTypes::PhaseSpace ) { Generator signalGenerator(events.eventType(), rndm); @@ -123,9 +132,11 @@ template void generateEvents( EventList& events else { FATAL("Phase space configuration: " << phsp_type << " is not supported"); } + } } + int main( int argc, char** argv ) { OptionsParser::setArgs( argc, argv ); @@ -196,10 +207,10 @@ int main( int argc, char** argv ) PolarisedSum pdf(eventType, MPS); generateEvents( accepted, pdf, phspType, nEvents, blockSize, &rand ); } - // else if ( pdfType == pdfTypes::FixedLib ){ - // FixedLibPDF pdf(lib); - // generateEvents( accepted, pdf, phspType, nEvents, blockSize, &rand, false ); - // } + else if ( pdfType == pdfTypes::FixedLib ){ + FixedLibPDF pdf(lib); + generateEvents( accepted, pdf, phspType, nEvents, blockSize, &rand, false ); + } else { FATAL("Did not recognise configuration: " << pdfType ); } diff --git a/src/DiracMatrices.cpp b/src/DiracMatrices.cpp index 938c41de246..a17c6d64ebe 100644 --- a/src/DiracMatrices.cpp +++ b/src/DiracMatrices.cpp @@ -23,6 +23,20 @@ extern const std::array AmpGen::Sigma( { Tensor({ Z,-I, I, Z}, Tensor::dim(2,2)), Tensor({ 1, 0, 0,-1}, Tensor::dim(2,2))} ); +extern const std::array AmpGen::Sigma4( { + Tensor({ 0, 1, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 1, + 0, 0, 1, 0 }, Tensor::dim(4,4)), + Tensor({ Z,-I, Z, Z, + I, Z, Z, Z, + Z, Z, Z, -I, + Z, Z, I, Z }, Tensor::dim(4,4)), + Tensor({ 1, 0, 0, 0, + 0, -1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, -1 }, Tensor::dim(4,4))} ); + extern const std::array AmpGen::S03 ( { Tensor({ 0, 0, 0, 0, 0, 0,-1, 0, 0, 1, 0, 0, 0, 0, 0, 0 }, Tensor::dim(4,4) ), Tensor({ 0, 0, 1, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0 }, Tensor::dim(4,4) ), diff --git a/src/Particle.cpp b/src/Particle.cpp index 00e31034e6f..e625687e659 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -167,6 +167,7 @@ void Particle::pdgLookup() m_lineshape = m_lineshape + "." + m_defaultModifier.getVal(); } bool isStrong = quarks() == daughterQuarks(); + if( abs(m_props->pdgID()) == 24 || abs(m_props->pdgID()) == 23 ) isStrong = false; if ( m_name.find( "NonRes" ) != std::string::npos ) isStrong = true; m_minL = m_daughters.size() == 2 ? orbitalRange( isStrong ).first : 0; if ( m_daughters.size() == 2 ) { @@ -519,19 +520,18 @@ Tensor Particle::externalSpinTensor(const int& polState, DebugSymbols* db ) cons { if( m_spinBasis == spinBasis::Weyl ) { + std::array xi; Expression n = fcn::sqrt( 2 * pP*(pP+pZ) ); - double isqrt_two = 1./sqrt(2); - Expression fa = m_props->isNeutrino() ? 2 : fcn::sqrt(pE/m + 1); - Expression fb = m_props->isNeutrino() ? 0 : fcn::sqrt(pE/m - 1); - Expression aligned = make_cse( Abs(pP + pZ) < 10e-6 ) ; - Expression xi10 = make_cse(Ternary( aligned, 1, (pP+pZ)/n )); - Expression xi11 = make_cse(Ternary( aligned, 0, z/n )); - Expression xi00 = make_cse(Ternary( aligned, 0, -zb/n )); - Expression xi01 = make_cse(Ternary( aligned, 1, (pP+pZ)/n )); - if(id > 0 && polState == 1) return isqrt_two * Tensor({ fa*xi10, fa*xi11, fb*xi10, fb*xi11 } ); - if(id > 0 && polState == -1) return isqrt_two * Tensor({ fa*xi00, fa*xi01, -fb*xi00, -fb*xi01 } ); - if(id < 0 && polState == 1) return isqrt_two * Tensor({ fb*xi00, fb*xi01, -fa*xi00, -fa*xi01 } ); - if(id < 0 && polState == -1) return isqrt_two * Tensor({ fb*xi10, fb*xi11, -fa*xi01, -fa*xi11 } ); + + xi[0] = Tensor( {-zb/n , (pP+pZ)/n}); + xi[1] = Tensor( {(pP+pZ)/n, z/n }); + + Expression fa = m_props->isNeutrino() ? polState * fcn::sqrt(pE) : polState * fcn::sqrt( pE/m- 1 ); + Expression fb = m_props->isNeutrino() ? fcn::sqrt(pE) : fcn::sqrt( pE/m + 1 ); + int ind = (id>0 ? polState : -polState) == -1 ? 0 : 1; + + return id > 0 ? Tensor({ - fa * xi[ind][0], - fa * xi[ind][1], fb * xi[ind][0], fb * xi[ind][1] }) + : -polState * Tensor({ fb * xi[ind][0], fb * xi[ind][1], fa * xi[ind][0], fa * xi[ind][1] }); } if ( m_spinBasis == spinBasis::Dirac ) { @@ -716,7 +716,7 @@ std::string Particle::topologicalString() const const ParticleProperties* Particle::props() const { return m_props; } bool Particle::isHead() const { return m_parent == nullptr; } -bool Particle::isWeakDecay() const { return quarks() == daughterQuarks(); } +bool Particle::isWeakDecay() const { return quarks() != daughterQuarks(); } bool Particle::isStateGood() const { return m_isStateGood; } bool Particle::isStable() const { return m_daughters.size() == 0; } diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 5994eb171c3..45b0a1bd755 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -61,6 +61,7 @@ PolarisedSum::PolarisedSum(const EventType& type, { std::string objCache = NamedParameter("PolarisedSum::ObjectCache", "" ); spaceType stype = NamedParameter( "PolarisedSum::SpaceType" , spaceType::spin); + { ThreadPool tp(std::thread::hardware_concurrency() ); if( stype == spaceType::spin ) { @@ -74,20 +75,23 @@ PolarisedSum::PolarisedSum(const EventType& type, for(unsigned i = 0; i < m_matrixElements.size(); ++i) { auto [lp, lc] = protoAmps[i]; - tp.enqueue( [i, p=lp, c=lc, polStates, &mps, this] () mutable { + auto & p = lp; + auto & c = lc; + PolarisedSum* ptr = this; + tp.enqueue( [i, p=lp, c=lc, polStates, &mps, ptr] () mutable { Tensor thisExpression( Tensor::dim(polStates.size()) ); DebugSymbols syms; for(unsigned j = 0; j != polStates.size(); ++j) - thisExpression[j] = make_cse( p.getExpression(j == 0 ? &syms: nullptr, polStates[j] ) ); - - this->m_matrixElements[i] = TransitionMatrix( + //thisExpression[j] = make_cse( p.getExpression(j == 0 ? &syms: nullptr, polStates[j] ) ); + thisExpression[j] = make_cse( p.getExpression(&syms, polStates[j] ) ); + ptr->m_matrixElements[i] = TransitionMatrix( p, c, CompiledExpression( TensorExpression(thisExpression), p.decayDescriptor(), &mps, - this->m_eventType.getEventFormat(), this->m_debug ? syms : DebugSymbols() ) ); + ptr->m_eventType.getEventFormat(), ptr->m_debug ? syms : DebugSymbols() ) ); - CompilerWrapper().compile( m_matrixElements[i] ); - m_matrixElements[i].size = thisExpression.size(); + CompilerWrapper().compile( ptr->m_matrixElements[i] ); + ptr->m_matrixElements[i].size = thisExpression.size(); }); } } @@ -114,6 +118,7 @@ PolarisedSum::PolarisedSum(const EventType& type, }); } } + } if( m_pVector.size() == 0 ) { auto p = [this](const std::string& name){ return this->m_mps->addOrGet(name, Flag::Fix, 0, 0); }; @@ -125,7 +130,7 @@ PolarisedSum::PolarisedSum(const EventType& type, DebugSymbols db; auto prob = probExpression(transitionMatrix(), convertProxies(m_pVector,[](auto& p){ return Parameter(p->name());} ), m_debug ? &db : nullptr); - m_probExpression = make_expression( prob, "prob_unnormalised", m_mps ); + m_probExpression = make_expression( prob, "prob_unnormalised", m_mps, this->m_debug ? db : DebugSymbols() ); } std::vector PolarisedSum::polarisations( const std::string& name ) const @@ -254,13 +259,14 @@ size_t PolarisedSum::size() const void PolarisedSum::reset( const bool& flag ){ m_nCalls = 0 ; } -Tensor PolarisedSum::transitionMatrix() +Tensor PolarisedSum::transitionMatrix() const { auto size = m_dim.first * m_dim.second; std::vector expressions(size, 0); unsigned totalSize = 0 ; - for( auto& me : m_matrixElements ){ - auto coupling = me.coupling.to_expression() ; + for( const auto& me : m_matrixElements ){ + auto coupling = me.coupling.to_expression(); + INFO( me.decayDescriptor() << " " << coupling ); auto cacheIndex = totalSize; for( size_t i = 0 ; i < size ; ++i ){ expressions[i] = expressions[i] + coupling * Parameter( "x1["+std::to_string(cacheIndex+i)+"]",0,true); @@ -325,8 +331,11 @@ void PolarisedSum::debug(const Event& evt) { std::vector this_cache; for(unsigned i = 0 ; i != tsize; ++i ) this_cache.emplace_back( m_cache(evt.index() / utils::size::value, j*tsize + i) ); - INFO( m_matrixElements[j].decayDescriptor() << " " << vectorToString( this_cache, " ") ); - if( m_debug ) m_matrixElements[0].debug( evt ); + INFO( m_matrixElements[j].decayDescriptor() << " " << vectorToString(this_cache, " ") ); + if( m_debug ){ + m_matrixElements[0].debug( evt ); + m_probExpression.debug(this_cache.data() ); + } } INFO("P(x) = " << getValNoCache(evt) << " " << operator()((const float_v*)nullptr, evt.index() / utils::size::value ) ); INFO("Prod = [" << vectorToString(m_pVector , ", ") <<"]"); @@ -398,6 +407,7 @@ Expression PolarisedSum::probExpression(const Tensor& T_matrix, const std::vecto rho(2,2) = 1. - 1.5*pz + sqrt(1.5)*Tzz; } ADD_DEBUG_TENSOR(T_matrix, db); + ADD_DEBUG_TENSOR(T_conj, db); ADD_DEBUG_TENSOR(rho, db); ADD_DEBUG_TENSOR(TT , db); Expression rt = rho(a,b) * TT(b,a); diff --git a/src/Spline.cpp b/src/Spline.cpp index bcdc41bf3ce..ed4fcf38530 100644 --- a/src/Spline.cpp +++ b/src/Spline.cpp @@ -63,7 +63,7 @@ Expression Spline::eval(DebugSymbols* db) const double spacing = ( m_max - m_min ) / ( (double)m_nKnots - 1. ); Expression dx = Fmod( x - m_min, spacing ); Expression bin = ( x - m_min ) / spacing; - Expression continuedValue = 0; + Expression continuedValue = m_points[m_nKnots-1]; Expression returnValue = Ternary( x > m_min && x < m_max, m_points[bin] + ( ( m_points[bin + 1] - m_points[bin] ) / spacing diff --git a/src/Tensor.cpp b/src/Tensor.cpp index 5195f2299bf..90ae8a46863 100644 --- a/src/Tensor.cpp +++ b/src/Tensor.cpp @@ -413,9 +413,6 @@ TensorProxy AmpGen::operator*( const TensorProxy& t1, const TensorProxy& t2 ) Tensor value( finalTensorRank ); unsigned nElem = value.nElements(); - //DEBUG("Got " << t1_tensor.dims().size() << " x " << t2_tensor.dims().size() << " with " << contractions.size() << " contractions " << nElementsInSum); - //DEBUG(t1_tensor.dimString() << " x " << t2_tensor.dimString() << " -> " << value.dimString()); - //DEBUG("Contraction matrix = " << "[" << vectorToString(contractionMatrix, ", ") << "]"); for( unsigned elem = 0; elem < nElem; ++elem ) { auto coords = Tensor::index_to_coordinates( elem, finalTensorRank ); diff --git a/src/Vertex.cpp b/src/Vertex.cpp index 2a3029e7f21..f86045f0604 100644 --- a/src/Vertex.cpp +++ b/src/Vertex.cpp @@ -426,11 +426,15 @@ DEFINE_VERTEX( V_ff_S1 ){ return Bar(V2)(a) * Gamma[4](a,b) * Gamma4Vec()(mu,b,c DEFINE_VERTEX( V_ff_PL ) { Tensor proj = Spin1Projector(P); + auto pl = 0.5 * ( Identity(4) - Gamma[4] ); + ADD_DEBUG_TENSOR( pl, db); + ADD_DEBUG_TENSOR( pl(b,c)* V2(c), db ); return proj(mu, nu) * Bar(V1)(a) * Gamma4Vec()(-nu,a,b) * ( Identity(4) - Gamma[4] )(b,c)* V2(c); } DEFINE_VERTEX( V_ff_PR ) { Tensor proj = Spin1Projector(P); + ADD_DEBUG_TENSOR( (Identity(4) + Gamma[4] )(b,c)* V2(c), db ); return proj(mu, nu) * Bar(V1)(a) * Gamma4Vec()(-nu,a,b) * ( Identity(4) + Gamma[4] )(b,c)* V2(c); } diff --git a/test/test_avx2d.cpp b/test/test_avx2d.cpp index a458fa294d9..049dc34b186 100644 --- a/test/test_avx2d.cpp +++ b/test/test_avx2d.cpp @@ -12,15 +12,21 @@ namespace utf = boost::unit_test; using namespace AmpGen; using namespace AmpGen::AVX2d; +using namespace std::complex_literals; + +#define test_simd( avx_function, scalar_function, data, tv) \ +{ auto r = avx_function( data ).to_array(); auto vals = data.to_array(); \ + for(int i =0;i!=4;++i) BOOST_TEST( r[i] == scalar_function(vals[i]), boost::test_tools::tolerance(tv) ); } BOOST_AUTO_TEST_CASE( test_log ) { - AVX2d::real_v p(0.3, 0.5, 10.0, 7.0); - auto logged = AVX2d::log( p ).to_array() ; - BOOST_TEST( logged[0] == std::log(0.3), boost::test_tools::tolerance(1e-12 ) ); - BOOST_TEST( logged[1] == std::log(0.5), boost::test_tools::tolerance(1e-12 ) ); - BOOST_TEST( logged[2] == std::log(10.0), boost::test_tools::tolerance(1e-12 ) ); - BOOST_TEST( logged[3] == std::log(7.0), boost::test_tools::tolerance(1e-12 ) ); + test_simd( AVX2d::log, std::log, AVX2d::real_v(0.3, 0.5, 10, 7.0), 1e-12 ); +} + +BOOST_AUTO_TEST_CASE( test_complex_log ) +{ + std::array, 4> pr = {0.3 - 3.0*1i, 0.5 - 4.0*1i, 10.+3.*1i, -4.0 + 1.0*1i}; + test_simd( AVX2d::log, std::log, AVX2d::complex_v( pr.data() ), 1e-8 ); } BOOST_AUTO_TEST_CASE( test_fmod ) @@ -32,7 +38,6 @@ BOOST_AUTO_TEST_CASE( test_fmod ) AVX2d::real_v bv( b.data() ); auto modv = AVX2d::fmod(av,bv); - BOOST_TEST_MESSAGE( "fmod = " << modv ); auto mod = modv.to_array(); BOOST_TEST( mod[0] == 2.1 , boost::test_tools::tolerance(1e-15)); @@ -68,27 +73,11 @@ BOOST_AUTO_TEST_CASE( test_gather ) BOOST_AUTO_TEST_CASE( test_trig ) { auto data = AVX2d::real_v(0.1,0.4,-2.0,5.0); - auto cos = AVX2d::cos(data).to_array(); - BOOST_TEST( cos[0] == std::cos( data.at(0 )) , boost::test_tools::tolerance(1e-15) ); - BOOST_TEST( cos[1] == std::cos( data.at(1 )) , boost::test_tools::tolerance(1e-15) ); - BOOST_TEST( cos[2] == std::cos( data.at(2)) , boost::test_tools::tolerance(1e-15) ); - BOOST_TEST( cos[3] == std::cos( data.at(3 )) , boost::test_tools::tolerance(1e-15) ); - - auto sin = AVX2d::sin(data).to_array(); - BOOST_TEST( sin[0] == std::sin( data.at(0 )) , boost::test_tools::tolerance(1e-15) ); - BOOST_TEST( sin[1] == std::sin( data.at(1 )) , boost::test_tools::tolerance(1e-15) ); - BOOST_TEST( sin[2] == std::sin( data.at(2)) , boost::test_tools::tolerance(1e-15) ); - BOOST_TEST( sin[3] == std::sin( data.at(3 )) , boost::test_tools::tolerance(1e-15) ); - - auto tan = AVX2d::tan(data).to_array(); - - BOOST_TEST( tan[0] == std::tan( data.at(0 )) , boost::test_tools::tolerance(1e-15) ); - BOOST_TEST( tan[1] == std::tan( data.at(1 )) , boost::test_tools::tolerance(1e-15) ); - BOOST_TEST( tan[2] == std::tan( data.at(2)) , boost::test_tools::tolerance(1e-15) ); - BOOST_TEST( tan[3] == std::tan( data.at(3 )) , boost::test_tools::tolerance(1e-15) ); + test_simd( AVX2d::cos, std::cos, data, 1e-15); + test_simd( AVX2d::sin, std::sin, data, 1e-15); + test_simd( AVX2d::tan, std::tan, data, 1e-15); } - #else BOOST_AUTO_TEST_CASE( test_dummy ) { From 08d32d095f1bca088943512158d2473c2f92e85c Mon Sep 17 00:00:00 2001 From: Timothy David Evans Date: Wed, 29 Jul 2020 18:01:35 +0200 Subject: [PATCH 212/250] fix debugging of |T|^2 in PolarisedSum --- src/PolarisedSum.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 45b0a1bd755..1f3f4407dfa 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -82,8 +82,8 @@ PolarisedSum::PolarisedSum(const EventType& type, Tensor thisExpression( Tensor::dim(polStates.size()) ); DebugSymbols syms; for(unsigned j = 0; j != polStates.size(); ++j) - //thisExpression[j] = make_cse( p.getExpression(j == 0 ? &syms: nullptr, polStates[j] ) ); - thisExpression[j] = make_cse( p.getExpression(&syms, polStates[j] ) ); + thisExpression[j] = make_cse( p.getExpression(j == 0 ? &syms: nullptr, polStates[j] ) ); + //thisExpression[j] = make_cse( p.getExpression(&syms, polStates[j] ) ); ptr->m_matrixElements[i] = TransitionMatrix( p, c, CompiledExpression( @@ -327,16 +327,14 @@ void PolarisedSum::updateNorms() void PolarisedSum::debug(const Event& evt) { auto tsize = m_dim.first * m_dim.second; + std::vector this_cache; for(unsigned j = 0; j != m_matrixElements.size(); ++j) { - std::vector this_cache; for(unsigned i = 0 ; i != tsize; ++i ) this_cache.emplace_back( m_cache(evt.index() / utils::size::value, j*tsize + i) ); INFO( m_matrixElements[j].decayDescriptor() << " " << vectorToString(this_cache, " ") ); - if( m_debug ){ - m_matrixElements[0].debug( evt ); - m_probExpression.debug(this_cache.data() ); - } - } + if( m_debug ) m_matrixElements[j].debug( evt ); + } + if( m_debug ) m_probExpression.debug(this_cache.data() ); INFO("P(x) = " << getValNoCache(evt) << " " << operator()((const float_v*)nullptr, evt.index() / utils::size::value ) ); INFO("Prod = [" << vectorToString(m_pVector , ", ") <<"]"); } From f88f7f66f474faf782bbf5ea9eedd98008cdc8b5 Mon Sep 17 00:00:00 2001 From: tevans Date: Thu, 30 Jul 2020 10:25:14 +0200 Subject: [PATCH 213/250] hopefully scalar builds don't accidentally include some AVX instructions --- CMakeLists.txt | 2 +- Standalone.cmake | 24 +++++++++++++----------- options/MintDalitzSpecialParticles.csv | 1 + src/Utilities.cpp | 1 + 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ad75fc9b283..f05bc3f941a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ if(COMMAND gaudi_subdir) LINK_LIBRARIES AmpGen) endforeach() else() - cmake_minimum_required(VERSION 3.12) + cmake_minimum_required(VERSION 3.11.1) project(AmpGen LANGUAGES CXX VERSION 2.0) include(Standalone.cmake) endif() diff --git a/Standalone.cmake b/Standalone.cmake index c2284d0e92e..03804d5cbef 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -166,26 +166,28 @@ target_compile_options(AmpGen -Wno-unknown-pragmas $<$:-O3>) -# if( NOT ${USE_SIMD} MATCHES "" ) - if ( ${USE_SIMD} MATCHES "AVX2d" ) +if ( ${USE_SIMD} MATCHES "AVX2d" ) message(STATUS "Enabling AVX2 [double precision]") target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=1" "ENABLE_AVX2d=1") target_compile_options(AmpGen PUBLIC -march=native -ftree-vectorize -mavx2 -ffast-math -DHAVE_AVX2_INSTRUCTIONS) - elseif ( ${USE_SIMD} MATCHES "AVX2f" ) +elseif ( ${USE_SIMD} MATCHES "AVX2f" ) message(STATUS "Enabling AVX2 [single precision]") target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=1" "ENABLE_AVX2f=1") target_compile_options(AmpGen PUBLIC -march=native -ftree-vectorize -mavx2 -ffast-math -DHAVE_AVX2_INSTRUCTIONS) - elseif ( ${USE_SIMD} MATCHES "AVX512d" ) +elseif ( ${USE_SIMD} MATCHES "AVX512d" ) message(STATUS "Enabling AVX2 [double precision]") target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=1" "ENABLE_AVX512=1") target_compile_options(AmpGen PUBLIC -march=native -ftree-vectorize -mavx512f -ffast-math -DHAVE_AVX512_INSTRUCTIONS) - endif() - if("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) - target_compile_options(AmpGen PUBLIC -mfma) - endif() - # else() - # message("SIMD disabled, resorting to scalar build : ${USE_SIMD}") - # endif() +else() + target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=0") + target_compile_options(AmpGen PUBLIC -march=x86-64) + message("SIMD disabled, resorting to scalar build : ${USE_SIMD}") +endif() + +if(${CMAKE_CXX_COMPILER_ID} MATCHES "AppleClang" OR + ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" ) + target_compile_options(AmpGen PUBLIC -mfma) +endif() if("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" ) target_link_libraries(AmpGen PUBLIC stdc++ ) diff --git a/options/MintDalitzSpecialParticles.csv b/options/MintDalitzSpecialParticles.csv index 00c3a6774b6..9ed8bdb1b0f 100644 --- a/options/MintDalitzSpecialParticles.csv +++ b/options/MintDalitzSpecialParticles.csv @@ -48,4 +48,5 @@ 1.86484E+03 ,1.7E-01,1.7E-01,1.605E-09 ,6.0E-12,6.0E-12,1/2, ,0 ,-, ,F, 998421, 0, ,R,D~ ,cU 3.8948E+03 ,1.1E-02,1.1E-02,2.96E+00 ,2.1E-03,2.1E-03,1 ,+,1 ,+,-, , 999443, 0, ,R,Z(c)(3900) ,cCuU 3.8948E+03 ,1.1E-02,1.1E-02,2.96E+00 ,2.1E-03,2.1E-03,1 ,+,1 ,+,-, , 999444, +, ,R,Z(c)(3900) ,cCuD +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1/2,+,0 ,+,+,F, 998140, 0, ,R,XiPi0 ,?? *** diff --git a/src/Utilities.cpp b/src/Utilities.cpp index a03553b20fc..60ba141d84e 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -331,6 +331,7 @@ std::string AmpGen::expandGlobals( std::string path ) } else { end_pos = find_next_of( path, {".", "/"}, pos ); variable_name = path.substr( pos + 1, end_pos - pos - 1 ); + end_pos--; } const char* global_var = getenv( variable_name.c_str() ); if ( global_var == nullptr ) { From 76fa62ab0e5deb5d692158547884a8499837c33a Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Aug 2020 19:39:37 +0200 Subject: [PATCH 214/250] change the way constants are encoded into strings to allow very large (or small) constants --- src/Expression.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Expression.cpp b/src/Expression.cpp index 64661e26c85..3ea94ad33de 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -52,9 +52,8 @@ bool isZero( const complex_t& A ){ std::string Constant::to_string(const ASTResolver* resolver) const { auto rounded_string = [](const double& val ){ - std::string str = std::to_string (val); - str.erase ( str.find_last_not_of('0') + 1, std::string::npos ); - return str; + std::string str = mysprintf("%g", val); + return str.find(".") != std::string::npos or str.find("e") != std::string::npos ? str : str + "."; }; std::string complex_type = type_string(); std::string literalSuffix = ""; From 5365228afabe1a34789946c6db848da784e58da1 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Aug 2020 20:26:26 +0200 Subject: [PATCH 215/250] possible fix in CompilerWrapper --- src/CompilerWrapper.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index 80962299085..64d9460f38f 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -166,9 +166,9 @@ void CompilerWrapper::compileSource( const std::string& fname, const std::string #if __APPLE__ argp.push_back("-lstdc++"); #endif - #ifdef _OPENMP - argp.push_back("-fopenmp=libiomp5"); - #endif +// #ifdef _OPENMP +// argp.push_back("-fopenmp=libiomp5"); +// #endif } argp.push_back( fname.c_str() ); From e83679b917729c9060bba553aafdfe6f184c4044 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Aug 2020 20:51:07 +0200 Subject: [PATCH 216/250] disable openmp for osx by default --- src/CompilerWrapper.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/CompilerWrapper.cpp b/src/CompilerWrapper.cpp index 64d9460f38f..da79239729a 100644 --- a/src/CompilerWrapper.cpp +++ b/src/CompilerWrapper.cpp @@ -131,12 +131,14 @@ bool CompilerWrapper::isClang() const return m_cxx.find("clang") != std::string::npos || m_cxx.find("llvm-g++") != std::string::npos; } -std::string get_cpp_version(){ +std::string get_cpp_version() +{ if( __cplusplus >= 201703L ) return "c++17"; if( __cplusplus >= 201402L ) return "c++14"; if( __cplusplus >= 201103L ) return "c++11"; else return ""; } + void CompilerWrapper::compileSource( const std::string& fname, const std::string& oname ) { using namespace std::chrono_literals; @@ -151,7 +153,7 @@ void CompilerWrapper::compileSource( const std::string& fname, const std::string compile_flags.push_back("-mavx2"); compile_flags.push_back("-DHAVE_AVX2_INSTRUCTIONS"); #endif - #ifdef _OPENMP + #if USE_OPENMP compile_flags.push_back("-fopenmp"); #endif @@ -166,9 +168,9 @@ void CompilerWrapper::compileSource( const std::string& fname, const std::string #if __APPLE__ argp.push_back("-lstdc++"); #endif -// #ifdef _OPENMP -// argp.push_back("-fopenmp=libiomp5"); -// #endif + #if USE_OPENMP + argp.push_back("-fopenmp=libiomp5"); + #endif } argp.push_back( fname.c_str() ); From 559e8ea98812b2d7c22b5f5c428893b8d1061772 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Aug 2020 21:16:58 +0200 Subject: [PATCH 217/250] fix openmp silliness --- Standalone.cmake | 4 +++- apps/DataConverter.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Standalone.cmake b/Standalone.cmake index 19c4076325c..8784ca4f74f 100644 --- a/Standalone.cmake +++ b/Standalone.cmake @@ -100,6 +100,7 @@ endif() target_link_libraries(AmpGen PUBLIC ROOT::Minuit2 ) if( USE_OPENMP ) + target_compile_definitions(AmpGen PUBLIC "USE_OPENMP=1") if(OpenMP_FOUND OR OpenMP_CXX_FOUND) if(NOT TARGET OpenMP::OpenMP_CXX) add_library(OpenMP::OpenMP_CXX IMPORTED INTERFACE) @@ -116,6 +117,8 @@ if( USE_OPENMP ) else() message(STATUS "OpenMP not found for CXX, you might have forgotten lb-run ROOT bash or CXX=`which g++` in CERN stack") endif() +else() + target_compile_definitions(AmpGen PUBLIC "USE_OPENMP=0") endif() set(RAPIDSIM_DATA "") @@ -154,7 +157,6 @@ target_compile_definitions(AmpGen PRIVATE "AMPGENROOT_CMAKE=\"${CMAKE_BINARY_DIR}/bin\"" "AMPGENROOT=\"${PROJECT_SOURCE_DIR}\"" "AMPGEN_CXX=\"${AMPGEN_CXX}\"" - "USE_OPENMP=\"${USE_OPENMP}\"" $<$:DEBUGLEVEL=1> $<$:TRACELEVEL=1>) diff --git a/apps/DataConverter.cpp b/apps/DataConverter.cpp index 8a41a628a0e..bde9ca91297 100644 --- a/apps/DataConverter.cpp +++ b/apps/DataConverter.cpp @@ -210,7 +210,7 @@ int main( int argc, char* argv[] ) p( evts ) -> Write(); // p( evts, WeightFunction([](auto& evt){ return 1; }), PlotOptions::Prefix("noweight") )->Write(); } - for( int i = 0 ; i != evtType.size(); ++i ) + for( unsigned i = 0 ; i != evtType.size(); ++i ) { Projection p( [i](auto& event){ return sqrt( event.s(i) ); }, "m_"+std::to_string(i), "m_"+std::to_string(i), 100, 0, 2.5 ); p(evts)->Write(); From d39508a1a2cf43f08e76192a5f9fbada8dc74967 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 5 Aug 2020 21:32:27 +0200 Subject: [PATCH 218/250] disable openmp in the travis job --- .ci/travis_osx.sh | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.ci/travis_osx.sh b/.ci/travis_osx.sh index 2ca3917298e..2c68f74053a 100644 --- a/.ci/travis_osx.sh +++ b/.ci/travis_osx.sh @@ -10,16 +10,9 @@ echo "Building under OS: $TRAVIS_OS_NAME" mkdir -p build cd build echo "CMake-ing, CXX = $CXX" -cmake .. -DCMAKE_CXX_COMPILER=clang -DUSE_SIMD="" +cmake .. -DCMAKE_CXX_COMPILER=clang -DUSE_SIMD="" -DUSE_OPENMP=0 echo "Building ..." cmake --build . -- -j2 cd .. echo "Running test job ..." ./build/bin/Generator options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 10000 -# echo -e 'travis_fold:end:script.build\\r' -# echo -en 'travis_fold:start:script.test\\r' -# echo "Testing..." -# set -evx - -# ctest --output-on-failure - From 754298aabb96b2dccff2df716b91354ca9e1f54d Mon Sep 17 00:00:00 2001 From: mstahl Date: Mon, 10 Aug 2020 12:53:43 +0200 Subject: [PATCH 219/250] [Lineshapes] Add production (P-)vector approach to GenericKmatrix and use it by default --- src/Lineshapes/GenericKmatrix.cpp | 115 +++++++++++++++++++----------- 1 file changed, 73 insertions(+), 42 deletions(-) diff --git a/src/Lineshapes/GenericKmatrix.cpp b/src/Lineshapes/GenericKmatrix.cpp index a6276f4156b..b66cbe9cda7 100644 --- a/src/Lineshapes/GenericKmatrix.cpp +++ b/src/Lineshapes/GenericKmatrix.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "AmpGen/Expression.h" #include "AmpGen/Factory.h" @@ -16,88 +17,118 @@ #include "AmpGen/Utilities.h" #include "AmpGen/kMatrix.h" #include "AmpGen/CoupledChannel.h" +#include "AmpGen/enum.h" using namespace AmpGen; -using namespace AmpGen::fcn; +using namespace AmpGen::fcn; +namespace AmpGen{ make_enum(PA_TYPE, PVec, QVec); } DEFINE_LINESHAPE(GenericKmatrix) { - auto props = ParticlePropertiesList::get( particleName ); - Expression mass = Parameter( particleName + "_mass", props->mass() ); - INFO( "kMatrix modifier " << lineshapeModifier << " particle = " << particleName ); - auto tokens = split(lineshapeModifier, '.' ); - DEBUG("kMatrix modifier = " << lineshapeModifier << " nTokens = " << tokens.size() ); - unsigned nPoles = NamedParameter( lineshapeModifier + "::kMatrix::nPoles"); - auto channels = NamedParameter(lineshapeModifier + "::kMatrix::channels").getVector(); - unsigned nChannels = channels.size(); - std::vector phsps; - std::vector bw_phase_space; - auto s0 = mass*mass; + auto props = ParticlePropertiesList::get( particleName ); + Expression mass = Parameter( particleName + "_mass", props->mass() ); + unsigned nPoles = NamedParameter(particleName+"::kMatrix::nPoles"); + auto channels = NamedParameter(particleName+"::kMatrix::channels").getVector(); + auto const pa_type = NamedParameter(particleName+"::kMatrix::production_amplitude",PA_TYPE::PVec); + auto nChannels = channels.size(); + auto s0 = mass*mass; + std::vector phsps, bw_phase_space; ADD_DEBUG(s, dbexpressions ); ADD_DEBUG(s0, dbexpressions ); - INFO("Initialising K-matrix with [nChannels = " << nChannels << ", nPoles = " << nPoles << "]"); + INFO("Initialising K-matrix with [nChannels = " << nChannels << ", nPoles = " << nPoles << "]"); + //phase-space for( unsigned i = 0 ; i < channels.size(); i+=1 ){ - Particle p( channels[i] ); + Particle p( channels[i] ); INFO( p.decayDescriptor() ); phsps.emplace_back( phaseSpace(s, p, p.L() ) ); bw_phase_space.emplace_back( phaseSpace(s0, p, p.L() ) ); if( dbexpressions != nullptr ) dbexpressions->emplace_back("phsp_"+p.decayDescriptor(), *phsps.rbegin() ); //ADD_DEBUG( *phsps.rbegin(), dbexpressions); -// ADD_DEBUG( phaseSpace(s0,p,p.L()), dbexpressions ); +// ADD_DEBUG( phaseSpace(s0,p,p.L()), dbexpressions ); } - Tensor non_resonant( Tensor::dim(nChannels, nChannels) ); + //pole configuration for kMatrix (see e.g. eq. (48.25) in http://pdg.lbl.gov/2019/reviews/rpp2019-rev-resonances.pdf) std::vector poleConfigs; for (unsigned pole = 1; pole <= nPoles; ++pole ){ - std::string stub = lineshapeModifier + "::pole::" + std::to_string(pole); + std::string stub = particleName+"::pole::" + std::to_string(pole); Expression mass = Parameter(stub + "::mass"); - INFO( "Will link to parameter: " << stub + "::mass"); + DEBUG( "Will link to parameter: " << stub + "::mass"); poleConfig thisPole(mass*mass); if( dbexpressions != nullptr ) dbexpressions->emplace_back(stub+"::mass", mass); Expression bw_width = 0; Expression bw_width0 = 0; - for (unsigned channel = 1; channel <= nChannels; ++channel ) - { + for (unsigned channel = 1; channel <= nChannels; ++channel ){ Expression g = Parameter(stub+"::g::"+std::to_string(channel)); - INFO("Will link to parameter: " << stub+"::g::"+std::to_string(channel) ); + DEBUG("Will link to parameter: " << stub+"::g::"+std::to_string(channel) ); thisPole.add(g, 1); - if( dbexpressions != nullptr ){ - dbexpressions->emplace_back( stub+"::g::"+std::to_string(channel), g); - } + if(dbexpressions != nullptr) dbexpressions->emplace_back( stub+"::g::"+std::to_string(channel), g); bw_width = bw_width + g*g*phsps[channel-1] / mass; bw_width0 = bw_width0 + g*g*bw_phase_space[channel-1] / mass; } - for( unsigned channel = 1 ; channel <= nChannels; ++channel ){ - Expression g = Parameter(stub+"::g::"+std::to_string(channel)); - Expression BR = g*g*bw_phase_space[channel-1] / ( mass * bw_width0 ); - ADD_DEBUG( BR, dbexpressions ); + if( dbexpressions != nullptr ){ + for( unsigned channel = 1 ; channel <= nChannels; ++channel ){ + Expression g = Parameter(stub+"::g::"+std::to_string(channel)); + Expression BR = g*g*bw_phase_space[channel-1] / ( mass * bw_width0 ); + ADD_DEBUG( BR, dbexpressions ); + } + ADD_DEBUG(bw_width, dbexpressions); + ADD_DEBUG(bw_width0, dbexpressions); } - ADD_DEBUG(bw_width, dbexpressions); - ADD_DEBUG(bw_width0, dbexpressions); poleConfigs.push_back(thisPole); } + //add non-resonant term to kMatrix (eq. (48.25) in http://pdg.lbl.gov/2019/reviews/rpp2019-rev-resonances.pdf) + Tensor non_resonant( Tensor::dim(nChannels, nChannels) ); for(unsigned ch1 = 1; ch1 <= nChannels; ++ch1){ for( unsigned ch2 = 1; ch2 <= nChannels; ++ch2 ){ auto c1 = std::to_string(ch1); - auto c2 = std::to_string(ch2); + auto c2 = std::to_string(ch2); if( ch1 > ch2 ) std::swap(c1,c2); - std::string nrShape = NamedParameter(lineshapeModifier +"::"+c1+"::"+c2+"::nrShape", "flat"); - Expression f1 = Parameter(lineshapeModifier+"::f1::"+c1+"::"+c2, 0); + std::string nrShape = NamedParameter(particleName+"::"+c1+"::"+c2+"::nrShape", "flat"); + Expression f1 = Parameter(particleName+"::f1::"+c1+"::"+c2, 0); if( nrShape == "flat") non_resonant[{ch1-1,ch2-1}] = f1; - else if( nrShape == "pole"){ - Expression f2 = Parameter(lineshapeModifier+"::f2::"+c1+"::"+c2, 0); - Expression s0 = Parameter(lineshapeModifier+"::s0::"+c1+"::"+c2, 0); + else if( nrShape == "pole"){ + Expression f2 = Parameter(particleName+"::f2::"+c1+"::"+c2, 0); + Expression s0 = Parameter(particleName+"::s0::"+c1+"::"+c2, 0); non_resonant[{ch1-1,ch2-1}] = (f1 + f2*sqrt(s)) / (s-s0); } - else WARNING("Unknown shape: " << nrShape); + else WARNING("Unknown shape: " << nrShape); } } + Tensor kMatrix = constructKMatrix(s, nChannels, poleConfigs); - ADD_DEBUG_TENSOR(kMatrix , dbexpressions); - kMatrix = kMatrix + non_resonant; + ADD_DEBUG_TENSOR(kMatrix, dbexpressions); + kMatrix = kMatrix + non_resonant; Tensor propagator = getPropagator(kMatrix, phsps); ADD_DEBUG_TENSOR(non_resonant, dbexpressions); - Expression M; - for(unsigned i = 0 ; i < nChannels; ++i) M = M + kMatrix[{i,0}] * propagator[{0,i}]; - return M ; // * phsps[0]; + + //we have all ingredients to build the production amplitude now + //follow https://doi.org/10.1007/s1010502a0002 eqns (9)-(13) modulo the Adler zero term (which is argued away in a fuzzy manner by citing a private communication) + if(pa_type==PA_TYPE::PVec){ + std::vector P(nChannels,0), a(nChannels,0), phi(nChannels,0);//the P-vector, a and phi coefficients + Expression s_0 = Parameter(particleName+"::s0"); + Expression F_0 = 0;//the object we'll return later: the production amplitude in the 0th channel + //get the coefficients first + for(unsigned k = 0 ; k < nChannels; ++k) a[k] = Parameter(particleName+"::a::"+std::to_string(k+1)); + //now start loop to calculate the production amplitude + for(unsigned k = 0 ; k < nChannels; ++k){ + for(unsigned alpha = 0; alpha < nPoles; ++alpha){ + Expression beta = 0; + for(unsigned q = 0 ; q < nChannels; ++q){ + beta += a[q] * poleConfigs[alpha].couplings[q]; + phi[k] += a[q] * non_resonant[{k,q}]; + } + P[k] += (beta * poleConfigs[alpha].couplings[k])/(poleConfigs[alpha].s - s) + phi[k] * (1.+s_0)/(s-s_0); + } + F_0 += propagator[{0,k}] * P[k]; + } + //TODO: implement higher orbital angular momentum + return F_0; + } + else if(pa_type==PA_TYPE::QVec){ + INFO("Using Q-vector approach to build the production amplitude"); + Expression M; + for(unsigned i = 0 ; i < nChannels; ++i) M = M + kMatrix[{i,0}] * propagator[{0,i}]; + return M ; // * phsps[0]; + } + else throw std::runtime_error("This shouldn't happen. Currently supported types: P-vector approach (PA_TYPE::PVec) and Q-vector approach (PA_TYPE::QVec)"); } From dde16712aea45ad71b7f3d4228b6ba12e881be55 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 10 Aug 2020 17:37:54 +0200 Subject: [PATCH 220/250] fix custom helicity couplings + cleanup of evaluation of PDFs to arbitrary datasets --- AmpGen/CoherentSum.h | 4 +-- AmpGen/KeyedFunctors.h | 31 ++++++++++++++++++++ AmpGen/LiteSpan.h | 42 --------------------------- AmpGen/MinuitParameter.h | 3 +- AmpGen/PolarisedSum.h | 2 +- AmpGen/Projection.h | 4 +-- AmpGen/SumPDF.h | 6 ++-- apps/ConvertToSourceCode.cpp | 55 ++++++++++++++++++------------------ src/CoherentSum.cpp | 23 ++++++++++----- src/MinuitParameter.cpp | 2 +- src/MinuitParameterSet.cpp | 12 ++------ src/Particle.cpp | 6 ++-- src/PolarisedSum.cpp | 52 +++++++++++++++++++--------------- 13 files changed, 119 insertions(+), 123 deletions(-) create mode 100644 AmpGen/KeyedFunctors.h delete mode 100644 AmpGen/LiteSpan.h diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index 9b0bf903f7c..297f4eb65c2 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -21,7 +21,7 @@ #include "AmpGen/Projection.h" #include "AmpGen/MinuitParameter.h" #include "AmpGen/Store.h" -#include "AmpGen/LiteSpan.h" +#include "AmpGen/KeyedFunctors.h" namespace AmpGen { class LinearErrorPropagator; @@ -99,7 +99,7 @@ namespace AmpGen Bilinears norms() const { return m_normalisations ; } std::function evaluator(const EventList_type* = nullptr) const; - KeyedFunctors componentEvaluator(const EventList_type* = nullptr) const; + KeyedFunctors componentEvaluator(const EventList_type* = nullptr) const; protected: std::vector> m_matrixElements; ///< Vector of matrix elements diff --git a/AmpGen/KeyedFunctors.h b/AmpGen/KeyedFunctors.h new file mode 100644 index 00000000000..c1c9fa7654a --- /dev/null +++ b/AmpGen/KeyedFunctors.h @@ -0,0 +1,31 @@ +#ifndef AMPGEN_LITESPAN_H +#define AMPGEN_LITESPAN_H + +#include "AmpGen/MsgService.h" +#include "AmpGen/Utilities.h" + +namespace AmpGen { + template struct KeyedFunctors; + + template struct KeyedFunctors + { + std::vector > functors; + std::vector keys; + std::vector titles; + template void add(const functor_type& functor, const std::string& key, const std::string& title="") + { + functors.push_back(functor); + keys.push_back(key); + titles.push_back(title); + } + std::vector operator()( arg_types... arg ) const + { + std::vector rt; + for( auto& f : functors ) rt.push_back( f(arg...) ); + return rt; + } + }; + +} + +#endif diff --git a/AmpGen/LiteSpan.h b/AmpGen/LiteSpan.h deleted file mode 100644 index e947665a4ef..00000000000 --- a/AmpGen/LiteSpan.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef AMPGEN_LITESPAN_H -#define AMPGEN_LITESPAN_H - -#include "AmpGen/MsgService.h" -#include "AmpGen/Utilities.h" - -namespace AmpGen { - // replace with std::span when c++20 becomes widespread - template class LiteSpan - { - public: - LiteSpan( const type* data, unsigned size =1) : m_data(data), m_size(size) {} - const type& operator[](const unsigned index) const { return m_data[index]; } - operator type() const { return m_data[0] ; } - unsigned size() const { return m_size; } - private: - const type* m_data = {nullptr}; - unsigned m_size = {0}; - }; - - template struct KeyedFunctors - { - std::vector > functors; - std::vector keys; - std::vector titles; - template - void add(const functor_type& functor, const std::string& key, const std::string& title="") - { - functors.push_back(functor); - keys.push_back(key); - titles.push_back(title); - } - std::vector operator()( const arg_type& arg ) const { - - std::vector rt; - for( auto& f : functors ) rt.push_back( f(arg) ); - return rt; } - }; - -} - -#endif diff --git a/AmpGen/MinuitParameter.h b/AmpGen/MinuitParameter.h index dbdaadf10bf..197f660ffb2 100644 --- a/AmpGen/MinuitParameter.h +++ b/AmpGen/MinuitParameter.h @@ -10,8 +10,7 @@ namespace AmpGen { class MinuitParameterSet; - declare_enum( Flag, Free, Hide, Fix, CompileTimeConstant ) - + declare_enum( Flag, Free, Hide, Fix, CompileTimeConstant, Invalid ) class MinuitParameter { public: diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index 70221e910e0..83ec58ccda2 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -72,7 +72,7 @@ namespace AmpGen Tensor transitionMatrix() const; const TransitionMatrix& operator[](const size_t& i) const { return m_matrixElements[i] ; } std::function evaluator(const EventList_type* = nullptr) const; - KeyedFunctors componentEvaluator(const EventList_type* = nullptr) const; + KeyedFunctors componentEvaluator(const EventList_type* = nullptr) const; private: size_t m_nCalls = {0}; real_t m_norm = {1}; diff --git a/AmpGen/Projection.h b/AmpGen/Projection.h index 8192ef58c25..ce91ffb9e1e 100644 --- a/AmpGen/Projection.h +++ b/AmpGen/Projection.h @@ -12,7 +12,7 @@ #include "AmpGen/ArgumentPack.h" #include "AmpGen/Types.h" -#include "AmpGen/LiteSpan.h" +#include "AmpGen/KeyedFunctors.h" namespace AmpGen { @@ -22,7 +22,7 @@ namespace AmpGen class Projection { - using keyedFunctors = KeyedFunctors; + using keyedFunctors = KeyedFunctors; public: Projection(); template diff --git a/AmpGen/SumPDF.h b/AmpGen/SumPDF.h index 830c7d4413c..e9663c5f127 100644 --- a/AmpGen/SumPDF.h +++ b/AmpGen/SumPDF.h @@ -5,7 +5,7 @@ #include "AmpGen/MetaUtils.h" #include "AmpGen/MsgService.h" #include "AmpGen/ProfileClock.h" -#include "AmpGen/LiteSpan.h" +#include "AmpGen/KeyedFunctors.h" #include #if ENABLE_AVX @@ -119,9 +119,9 @@ namespace AmpGen } ); return arrayToFunctor(values); } - KeyedFunctors componentEvaluator(const eventListType* events) const + KeyedFunctors componentEvaluator(const eventListType* events) const { - KeyedFunctors view; + KeyedFunctors view; for_each( this->m_pdfs, [&view, &events]( const auto& pdf) mutable { auto eval = pdf.evaluator(events); view.add([eval](const auto& event){ return eval(event) ; } , type_string(pdf), "" ); diff --git a/apps/ConvertToSourceCode.cpp b/apps/ConvertToSourceCode.cpp index 94ffd3f8567..e1695ff454c 100644 --- a/apps/ConvertToSourceCode.cpp +++ b/apps/ConvertToSourceCode.cpp @@ -71,31 +71,44 @@ void create_integration_tests(T& pdf, } */ -template void generate_source(T& pdf, EventList& normEvents, const std::string& sourceFile, MinuitParameterSet& mps, const double& sf) +template void generate_source(T& pdf, const std::string& sourceFile, MinuitParameterSet& mps, const double& sf) { bool normalise = NamedParameter("Normalise",true); - std::string type = NamedParameter("Type", "CoherentSum" ); + double safetyFactor = NamedParameter( "SafetyFactor", 3 ); + int seed = NamedParameter("Seed", 1); + size_t nEvents = NamedParameter( "NormEvents", 1000000 ); + auto oEventType = NamedParameter("EventType").getVector(); + + TRandom3 rnd(seed); + INFO("First random number = " << rnd.Uniform() ); + + EventType eventType( oEventType ); + Generator phsp(eventType); + phsp.setRandom(&rnd); + EventList normEvents = phsp.generate(nEvents); + if constexpr( std::is_same::value ) pdf.prepare(); double norm = 1; if( normalise ){ - double pMax = 0 ; - pdf.setEvents( normEvents ); - pdf.prepare(); - pdf.debug( normEvents[0] ); - for ( auto& evt : normEvents ) { - if( type == "PolarisedSum" ){ + double pMax = 0; + for ( auto& evt : normEvents ) + { + if constexpr ( std::is_same::value ) + { double px, py, pz; - gRandom->Sphere(px,py,pz, gRandom->Uniform(0,1)); + rnd.Sphere(px,py,pz, rnd.Uniform(0,1)); mps["Px"]->setCurrentFitVal(px); mps["Py"]->setCurrentFitVal(py); mps["Pz"]->setCurrentFitVal(pz); pdf.transferParameters(); } - double n = pdf(evt); + double n = 0; + if constexpr ( std::is_same::value ) n = std::norm( pdf.getValNoCache(evt) ); + if constexpr ( std::is_same::value ) n = pdf.getValNoCache(evt); if ( n > pMax ) pMax = n; } norm = pMax * sf ; - INFO( "Making binary with " << pMax << " x safety factor = " << sf ); + INFO( "Making binary with " << pMax << " x safety factor = " << sf ); } mps.resetToInit(); pdf.generateSourceCode( sourceFile, norm, true ); @@ -110,7 +123,7 @@ int main( int argc, char** argv ) std::string outputPS = NamedParameter( "OutputEvents", "" ); unsigned int NormEvents = NamedParameter( "NormEvents", 1000000 ); double safetyFactor = NamedParameter( "SafefyFactor", 3 ); - + unsigned seed = NamedParameter("Seed", 0); EventType eventType( oEventType ); AmpGen::MinuitParameterSet MPS; // @@ -122,28 +135,16 @@ int main( int argc, char** argv ) } Generator phsp( eventType ); TRandom3 rnd; - + rnd.SetSeed( seed ); gRandom = &rnd; phsp.setRandom( &rnd ); - EventList phspEvents( oEventType ); - phsp.fillEventListPhaseSpace( phspEvents, NormEvents ); - if( type == "CoherentSum" ){ CoherentSum sig( eventType, MPS, "" ); - generate_source( sig, phspEvents, sourceFile, MPS, safetyFactor ); - //create_integration_tests(sig, eventType, MPS, {phspEvents[15]}, sourceFile ); + generate_source( sig, sourceFile, MPS, safetyFactor ); } if( type == "PolarisedSum" ){ PolarisedSum sig( eventType, MPS ); - generate_source( sig, phspEvents, sourceFile, MPS, safetyFactor ); - } - if ( outputPS != "" ) { - std::ofstream ofile( outputPS ); - ofile << "0x,0y,0z,0t,1x,1y,1z,1t,2x,2y,2z,2t,3x,3y,3z,3t\n"; - for ( auto& event : phspEvents ) { - for ( size_t i = 0; i < event.size(); i++ ) ofile << ( i == 0 ? "" : "," ) << event[i]; - ofile << "\n"; - } + generate_source( sig, sourceFile, MPS, safetyFactor ); } } diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 980e224e060..378f50f2029 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -370,24 +370,33 @@ std::function CoherentSum::evaluator(const EventList_type* return arrayToFunctor(values); } -KeyedFunctors CoherentSum::componentEvaluator(const EventList_type* ievents) const +KeyedFunctors CoherentSum::componentEvaluator(const EventList_type* ievents) const { - auto& cache = m_integrator.cache(); - KeyedFunctors rt; + using store_t = Store; + auto events = ievents == nullptr ? m_integrator.events() : ievents; + KeyedFunctors rt; + std::shared_ptr cache; + if( events != m_integrator.events() ) + { + cache = std::make_shared(events->size(), m_matrixElements); + for( auto& me : m_matrixElements ) const_cast(cache.get())->update(events->store(), me); + } + else cache = std::shared_ptr( & m_integrator.cache(), [](const store_t* t){} ); + /// this little slice of weirdness allows either a new cache to be instantiated, or one to just get a pointer to the one used for the integration. + for( unsigned i = 0 ; i != m_matrixElements.size(); ++i ) { - for( unsigned j = i ; j != m_matrixElements.size(); ++j ){ + for( unsigned j = i ; j != m_matrixElements.size(); ++j ) + { auto mi = m_matrixElements[i]; auto mj = m_matrixElements[j]; auto ci = this->m_matrixElements[i].coefficient; auto cj = this->m_matrixElements[j].coefficient; double s = (i==j) ? 1 : 2 ; auto name = programatic_name(mi.decayTree.decayDescriptor()) + "_" + programatic_name( mj.decayTree.decayDescriptor() ); - INFO("Adding evaluator for: " << name ); - auto functor = [ci,cj,i,j,s, &cache](const Event& event){ return s * std::real( ci * cache.get( event.index(), i ) * std::conj( cj * cache.get( event.index(), j ) ) ) ;}; + auto functor = [ci,cj,i,j,s, cache](const Event& event){ return s * std::real( ci * cache->get( event.index(), i ) * std::conj( cj * cache->get( event.index(), j ) ) ) ;}; rt.add(functor, name, ""); } } - INFO(" Returning: " << rt.keys.size() << " functors" ); return rt; } diff --git a/src/MinuitParameter.cpp b/src/MinuitParameter.cpp index 896dc3a038d..b0913ea5ae3 100644 --- a/src/MinuitParameter.cpp +++ b/src/MinuitParameter.cpp @@ -10,7 +10,7 @@ using namespace AmpGen; namespace AmpGen { - complete_enum( Flag, Free, Hide, Fix, CompileTimeConstant ) + complete_enum( Flag, Free, Hide, Fix, CompileTimeConstant, Invalid ) } MinuitParameter::MinuitParameter( const std::string& name, const Flag& fix, const double& mean, const double& step, diff --git a/src/MinuitParameterSet.cpp b/src/MinuitParameterSet.cpp index 1bf0031846b..39ed23b5433 100644 --- a/src/MinuitParameterSet.cpp +++ b/src/MinuitParameterSet.cpp @@ -26,16 +26,6 @@ MinuitParameterSet::MinuitParameterSet(const std::vector& para for( auto& param : params ) add(param); } -// MinuitParameterSet MinuitParameterSet::getFloating() -// { -// MinuitParameterSet floating; -// for ( auto& param : *this ) { -// if ( param->isFree() && dynamic_cast(param) != nullptr ) -// floating.add(param); -// } -// return floating; -// } - bool MinuitParameterSet::addToEnd( MinuitParameter* parPtr ) { bool success = true; @@ -132,6 +122,7 @@ void MinuitParameterSet::tryParameter( const std::vector& line ) double max = hasLimits ? lexical_cast( line[5], status ) : 0; if( !status ) return; auto flag = parse( line[1] ); + if( flag == Flag::Invalid ) return; if ( OptionsParser::printHelp() ) INFO( "MINUIT: Registered " << line[0] << " ( " << to_string(flag) << ") = " << mean << ", step=" << step << " ("<< min << "," << max << ")" ); add( new MinuitParameter( line[0], flag, mean, step, min, max ) ); @@ -150,6 +141,7 @@ void MinuitParameterSet::tryParameter( const std::vector& line ) if ( !status ) return; auto flag_re = parse(line[1]); auto flag_im = parse(line[4 + 2*hasLimits]); + if( flag_re == Flag::Invalid || flag_im == Flag::Invalid ) return; if ( OptionsParser::printHelp() ) { INFO( "MINUIT: Complex " << line[0] << "_Re ( " << to_string(flag_re) << ") = " << mean_re << ", step=" << step_re << " (" << min_re << "," << max_re << ")" ); INFO( "MINUIT: Complex " << line[0] << "_Im ( " << to_string(flag_im) << ") = " << mean_im << ", step=" << step_im << " (" << min_im << "," << max_im << ")" ); diff --git a/src/Particle.cpp b/src/Particle.cpp index e625687e659..b03103ec569 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -522,9 +522,9 @@ Tensor Particle::externalSpinTensor(const int& polState, DebugSymbols* db ) cons { std::array xi; Expression n = fcn::sqrt( 2 * pP*(pP+pZ) ); - - xi[0] = Tensor( {-zb/n , (pP+pZ)/n}); - xi[1] = Tensor( {(pP+pZ)/n, z/n }); + Expression aligned = make_cse( Abs(pP + pZ) < 10e-6 ) ; + xi[0] = Tensor( {make_cse( Ternary(aligned, 1, -zb/n)) , make_cse( Ternary(aligned, 0, (pP+pZ)/n ) ) }); + xi[1] = Tensor( {make_cse( Ternary(aligned, 0, (pP+pZ)/n)), make_cse(Ternary(aligned,1, z/n) ) }); Expression fa = m_props->isNeutrino() ? polState * fcn::sqrt(pE) : polState * fcn::sqrt( pE/m- 1 ); Expression fb = m_props->isNeutrino() ? fcn::sqrt(pE) : fcn::sqrt( pE/m + 1 ); diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 1f3f4407dfa..75f6c2a42a0 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -266,7 +266,7 @@ Tensor PolarisedSum::transitionMatrix() const unsigned totalSize = 0 ; for( const auto& me : m_matrixElements ){ auto coupling = me.coupling.to_expression(); - INFO( me.decayDescriptor() << " " << coupling ); + // INFO( me.decayDescriptor() << " " << coupling ); auto cacheIndex = totalSize; for( size_t i = 0 ; i < size ; ++i ){ expressions[i] = expressions[i] + coupling * Parameter( "x1["+std::to_string(cacheIndex+i)+"]",0,true); @@ -498,15 +498,23 @@ std::function PolarisedSum::evaluator(const EventList_type { utils::store(values.data() + utils::size::value * block, (m_weight/m_norm) * m_probExpression(&store(block,0)) ); } - for( unsigned int i = 0 ; i != 10; ++i ) - DEBUG(values[i] << " " << getValNoCache( events->at(i) ) * ( m_weight / m_norm ) ); return arrayToFunctor(values); } -KeyedFunctors PolarisedSum::componentEvaluator(const EventList_type* events) const + +KeyedFunctors PolarisedSum::componentEvaluator(const EventList_type* ievents) const { - auto& cache = m_integrator.cache(); - KeyedFunctors rt; + using store_t = Store; + auto events = ievents == nullptr ? m_integrator.events() : ievents; + std::shared_ptr cache; + if( events != m_integrator.events() ) + { + cache = std::make_shared(events->size(), m_matrixElements, m_dim.first*m_dim.second); + for( auto& me : m_matrixElements ) const_cast(cache.get())->update(events->store(), me); + } + else cache = std::shared_ptr( & m_integrator.cache(), [](const store_t* t){} ); + + KeyedFunctors rt; for( unsigned i = 0 ; i != m_matrixElements.size(); ++i ) { for( unsigned j = i ; j != m_matrixElements.size(); ++j ){ @@ -516,23 +524,21 @@ KeyedFunctors PolarisedSum::componentEvaluator(const EventList_ty auto cj = this->m_matrixElements[j].coefficient; double s = (i==j) ? 1 : 2 ; auto name = programatic_name(mi.decayTree.decayDescriptor()) + "_" + programatic_name( mj.decayTree.decayDescriptor() ); - INFO("Adding evaluator for: " << name ); - auto functor = [ci,cj,i,j,s, &cache, this](const Event& event){ - auto [s1,s2] = this->m_dim; - auto R = s1 * s2; - complex_t total = 0; - for( unsigned x = 0; x != this->m_norms.size(); ++x ) - { - auto f = x % s2; - auto psiIndex = (x-f) / s2; - auto m2 = psiIndex % s1; - auto m1 = (psiIndex-m2)/s1; - total += this->m_rho[psiIndex] * ci * cache.get(event.index(),R * i + m1 * s2 + f) - * std::conj( cj * cache.get(event.index(),R * j + m2 * s2 + f) ); - } - return s * std::real(total); - }; - rt.add(functor, name, ""); + rt.add( [ci,cj,i,j,s, cache, this](const Event& event){ + auto [s1,s2] = this->m_dim; + auto R = s1 * s2; + complex_t total = 0; + for( unsigned x = 0; x != this->m_norms.size(); ++x ) + { + auto f = x % s2; + auto psiIndex = (x-f) / s2; + auto m2 = psiIndex % s1; + auto m1 = (psiIndex-m2)/s1; + total += this->m_rho[psiIndex] * ci * cache->get(event.index(),R * i + m1 * s2 + f) + * std::conj( cj * cache->get(event.index(),R * j + m2 * s2 + f) ); + } + return s * std::real(total); + }, name, ""); } } return rt; From fa24e34854fe35a8b126464b890f82df2f48e2ee Mon Sep 17 00:00:00 2001 From: mstahl Date: Mon, 10 Aug 2020 17:39:33 +0200 Subject: [PATCH 221/250] [example apps] add BaryonFitter and fit_hyperon_parameters.cpp --- examples/BaryonFitter.cpp | 230 ++++++++++++++++++++++++++++ examples/fit_hyperon_parameters.cpp | 22 +++ 2 files changed, 252 insertions(+) create mode 100644 examples/BaryonFitter.cpp create mode 100644 examples/fit_hyperon_parameters.cpp diff --git a/examples/BaryonFitter.cpp b/examples/BaryonFitter.cpp new file mode 100644 index 00000000000..4b20e83952a --- /dev/null +++ b/examples/BaryonFitter.cpp @@ -0,0 +1,230 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "AmpGen/Chi2Estimator.h" +#include "AmpGen/ErrorPropagator.h" +#if ENABLE_AVX + #include "AmpGen/EventListSIMD.h" + using EventList_type = AmpGen::EventListSIMD; +#else + #include "AmpGen/EventList.h" + using EventList_type = AmpGen::EventList; +#endif +#include "AmpGen/EventType.h" +#include "AmpGen/Factory.h" +#include "AmpGen/RecursivePhaseSpace.h" +#include "AmpGen/FitResult.h" +#include "AmpGen/IExtendLikelihood.h" +#include "AmpGen/Minimiser.h" +#include "AmpGen/MinuitParameter.h" +#include "AmpGen/MinuitParameterSet.h" +#include "AmpGen/MsgService.h" +#include "AmpGen/NamedParameter.h" +#include "AmpGen/SumPDF.h" +#include "AmpGen/ThreeBodyCalculators.h" +#include "AmpGen/Utilities.h" +#include "AmpGen/Generator.h" +#include "AmpGen/PolarisedSum.h" +#include "AmpGen/Kinematics.h" + +#ifdef _OPENMP + #include + #include +#endif + +using namespace AmpGen; + +void randomizeStartingPoint( MinuitParameterSet& mps, TRandom3& rand) +{ + for (auto& param : mps) { + if ( ! param->isFree() || param->name() == "Px" || param->name() == "Py" || param->name() == "Pz" ) continue; + double min = param->minInit(); + double max = param->maxInit(); + double new_value = rand.Uniform(param->mean()-param->stepInit(),param->mean()+param->stepInit()); + if( min != 0 && max != 0 ) + new_value = rand.Uniform(min,max); + param->setInit( new_value ); + param->setCurrentFitVal( new_value ); + INFO( param->name() << " = " << param->mean() << " " << param->stepInit() ); + } +} + +template +FitResult* doFit( PDF&& pdf, EventList_type& data, EventList_type& mc, MinuitParameterSet& MPS ) +{ + auto time_wall = std::chrono::high_resolution_clock::now(); + auto time = std::clock(); + + pdf.setEvents( data ); + + /* Minimiser is a general interface to Minuit1/Minuit2, + that is constructed from an object that defines an operator() that returns a double + (i.e. the likielihood, and a set of MinuitParameters. */ + Minimiser mini( pdf, &MPS ); + mini.doFit(); + FitResult* fr = new FitResult(mini); + + /* Estimate the chi2 using an adaptive / decision tree based binning, + down to a minimum bin population of 15, and add it to the output.*/ + //if(data.eventType().size() < 5){ + // Chi2Estimator chi2( data, mc, pdf, 15 ); + // //chi2.writeBinningToFile("chi2_binning.txt"); + // fr->addChi2( chi2.chi2(), chi2.nBins() ); + //} + + auto twall_end = std::chrono::high_resolution_clock::now(); + double time_cpu = ( std::clock() - time ) / (double)CLOCKS_PER_SEC; + double tWall = std::chrono::duration( twall_end - time_wall ).count(); + INFO( "Wall time = " << tWall / 1000. ); + INFO( "CPU time = " << time_cpu ); + fr->print(); + + /* Save weighted data and norm MC for the different components in the PDF, i.e. the signal and backgrounds. + The structure assumed the PDF is some SumPDF. */ + unsigned int counter = 1; + for_each(pdf.pdfs(), [&]( auto& f ){ + mc.transform([&f](auto& mcevt){mcevt.setWeight(f.getValNoCache(mcevt)*mcevt.weight()/mcevt.genPdf());}).tree(counter>1?"MCt"+std::to_string(counter):"MCt")->Write(); + data.tree(counter>1?"t"+std::to_string(counter):"t")->Write(); + counter++; + } ); + + return fr; +} + +void invertParity( Event& event, const size_t& nParticles=0) +{ + for( size_t i = 0 ; i < nParticles; ++i ) + { + event[4*i + 0] = -event[4*i+0]; + event[4*i + 1] = -event[4*i+1]; + event[4*i + 2] = -event[4*i+2]; + } +} + +int main( int argc, char* argv[] ) +{ + gErrorIgnoreLevel = 1001; + + OptionsParser::setArgs( argc, argv ); + + const std::vector dataFile = NamedParameter("DataSample","").getVector(); + const std::string simFile = NamedParameter("SimFile", "" , "Name of file containing simulated sample for using in MC integration"); + const std::string logFile = NamedParameter("LogFile","Fitter.log"); + const std::string plotFile = NamedParameter("Plots","plots.root"); + const std::string prefix = NamedParameter("PlotPrefix",""); + const std::string idbranch = NamedParameter("IDBranch",""); + const std::string mcidbranch = NamedParameter("MCIDBranch",""); + const std::string weight_branch = NamedParameter("WeightBranch","","Name of branch containing event weights."); + const std::string mc_weight_branch = NamedParameter("MCWeightBranch","","Name of branch containing event weights."); + + const auto nev_MC = NamedParameter("NEventsMC", 8e6, "Number of MC events for normalization."); + auto bNames = NamedParameter("Branches", std::vector(), + "List of branch names, assumed to be \033[3m daughter1_px ... daughter1_E, daughter2_px ... \033[0m" ).getVector(); + auto MCbNames = NamedParameter("MCBranches", std::vector(), + "List of branch names, assumed to be \033[3m daughter1_px ... daughter1_E, daughter2_px ... \033[0m" ).getVector(); + auto pNames = NamedParameter("EventType" , "" + , "EventType to fit, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(); + +#ifdef _OPENMP + unsigned int concurentThreadsSupported = std::thread::hardware_concurrency(); + unsigned int nThreads = NamedParameter( "nCores", concurentThreadsSupported ); + omp_set_num_threads( nThreads ); + INFO( "Setting " << nThreads << " fixed threads for OpenMP" ); + omp_set_dynamic( 0 ); +#endif + + + /* A MinuitParameterSet is (unsurprisingly) a set of fit parameters, and can be loaded from + the parsed options. For historical reasons, this is referred to as loading it from a "Stream" */ + MinuitParameterSet MPS; + MPS.loadFromStream(); + TRandom3 rndm = TRandom3( NamedParameter("Seed", 1 ) ) ; + if( NamedParameter("RandomizeStartingPoint",false) ) randomizeStartingPoint(MPS,rndm ); + + /* An EventType specifies the initial and final state particles as a vector that will be described by the fit. + It is typically loaded from the interface parameter EventType. */ + EventType evtType(pNames); + + /* A CoherentSum is the typical amplitude to be used, that is some sum over quasi two-body contributions + weighted by an appropriate complex amplitude. The CoherentSum is generated from the couplings described + by a set of parameters (in a MinuitParameterSet), and an EventType, which matches these parameters + to a given final state and a set of data. A common set of rules can be matched to multiple final states, + i.e. to facilitate the analysis of coupled channels. */ + PolarisedSum sig(evtType, MPS); + + /* Events are read in from ROOT files. If only the filename and the event type are specified, + the file is assumed to be in the specific format that is defined by the event type, + unless the branches to load are specified in the user options */ + EventList_type events(dataFile, evtType, Branches(bNames), GetGenPdf(false), WeightBranch(weight_branch), ExtraBranches(std::vector{idbranch}) ); + + /* Generate events to normalise the PDF with. This can also be loaded from a file, + which will be the case when efficiency variations are included. */ + EventList_type eventsMC = simFile == "" + ? EventList_type(Generator(sig.matrixElements()[0].decayTree.quasiStableTree(), events.eventType(), &rndm).generate(nev_MC)) + : EventList_type(simFile, evtType, Branches(MCbNames), WeightBranch(mc_weight_branch), ExtraBranches(std::vector{mcidbranch})); + + /* Transform data if we have an ID brach. That branch indicates that we operate on a sample with particles+antiparticles mixed. + The transformation also includes boosting to the restframe of the head of the decay chain. + TODO: There might be situations where you want to separate both transformations */ + auto const n_final_state_particles = evtType.size(); + std::vector daughters_as_ints(n_final_state_particles); + std::iota (daughters_as_ints.begin(), daughters_as_ints.end(), 0u); + auto frame_transform = [&evtType, &daughters_as_ints, &n_final_state_particles](auto& event){ + TVector3 pBeam(0,0,1); + if( event[event.size()-1] < 0 ){ + invertParity( event, n_final_state_particles); + pBeam = -pBeam; + } + TLorentzVector pP = pFromEvent(event,daughters_as_ints); + //if( pP.P() < 10e-5) return; + TVector3 pZ = pP.Vect(); + rotateBasis( event, (pBeam.Cross(pZ) ).Cross(pZ), pBeam.Cross(pZ), pZ ); + boost( event, {0, 0, -1}, pP.P()/pP.E() ); + }; + + + for( auto& event : events ) + if( event[event.size()-1] < 0 ){ + event.print(); + break; + } + events.transform( frame_transform ); + for( auto& event : events ) + if( event[event.size()-1] < 0 ){//E if there's no ID branch + event.print(); + break; + } + for( auto& event : eventsMC ) + if( event[event.size()-1] < 0 ){ + event.print(); + break; + } + eventsMC.transform( frame_transform ); + for( auto& event : eventsMC ) + if( event[event.size()-1] < 0 ){//E if there's no ID branch + event.print(); + break; + } + sig.setMC(eventsMC); + sig.setEvents(events); + + TFile* output = TFile::Open( plotFile.c_str(), "RECREATE" ); + output->cd(); + auto fr = doFit(make_pdf(sig), events, eventsMC, MPS); + + auto ff = sig.fitFractions( fr->getErrorPropagator() ); + fr->addFractions(ff); + fr->writeToFile( logFile ); + output->Close(); + return 0; +} diff --git a/examples/fit_hyperon_parameters.cpp b/examples/fit_hyperon_parameters.cpp new file mode 100644 index 00000000000..ccb856cfe76 --- /dev/null +++ b/examples/fit_hyperon_parameters.cpp @@ -0,0 +1,22 @@ +#include "AmpGen/MinuitParameterSet.h" +#include "AmpGen/Minimiser.h" +#include "AmpGen/NamedParameter.h" + +using namespace AmpGen; + +int main( int argc, char* argv[] ){ + OptionsParser::setArgs( argc, argv ); + MinuitParameterSet mps; + mps.add("gRe",AmpGen::Flag::Free,0,0.1,-10,10); + mps.add("gIm",AmpGen::Flag::Free,0,0.1,-10,10); + const auto alpha_measured = NamedParameter("alpha", 0.75); + const auto phi_measured = NamedParameter("phi", -6.5); + const auto alpha_error = NamedParameter("alpha_error", 0.012); + const auto phi_error = NamedParameter("phi_error", 3.5); + std::function f = [&mps, &alpha_measured, &alpha_error, &phi_measured, &phi_error]() -> double { + auto alpha_pred = 2.*mps[0]->mean()/(1.+mps[0]->mean()*mps[0]->mean()+mps[1]->mean()*mps[1]->mean()); + auto phi_pred = 180.*atan(2.*mps[1]->mean()/(1.-(mps[0]->mean()*mps[0]->mean()+mps[1]->mean()*mps[1]->mean())))/M_PI; + return pow((alpha_measured-alpha_pred)/alpha_error,2.)+pow((phi_measured-phi_pred)/phi_error,2.); + }; + Minimiser(f, &mps).doFit(); +} From d50abb1af887fcab54e18aabd3fda3f8d8223f3a Mon Sep 17 00:00:00 2001 From: mstahl Date: Mon, 10 Aug 2020 17:42:38 +0200 Subject: [PATCH 222/250] [SumPDF] use event weight in fit --- AmpGen/SumPDF.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AmpGen/SumPDF.h b/AmpGen/SumPDF.h index 830c7d4413c..0255a41f0c3 100644 --- a/AmpGen/SumPDF.h +++ b/AmpGen/SumPDF.h @@ -64,7 +64,8 @@ namespace AmpGen #pragma omp parallel for reduction( +: LL ) for ( unsigned int i = 0; i < m_events->size(); ++i ) { auto prob = ((*this))(( *m_events)[i] ); - LL += log(prob); + auto w = (*m_events)[i].weight(); + LL += w*log(prob); } return -2 * LL; } From 8982ae888b4f65f8236556ff933c2744169969c5 Mon Sep 17 00:00:00 2001 From: mstahl Date: Mon, 10 Aug 2020 21:33:58 +0200 Subject: [PATCH 223/250] [BaryonFitter] throw error when adding branches and using AVX; [Minimiser] add option to run Minos --- examples/BaryonFitter.cpp | 7 +++++++ src/Minimiser.cpp | 38 +++++++++++++++++++------------------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/examples/BaryonFitter.cpp b/examples/BaryonFitter.cpp index 4b20e83952a..a4657e804bb 100644 --- a/examples/BaryonFitter.cpp +++ b/examples/BaryonFitter.cpp @@ -135,6 +135,13 @@ int main( int argc, char* argv[] ) auto pNames = NamedParameter("EventType" , "" , "EventType to fit, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(); +#if ENABLE_AVX + if(!idbranch.empty() || !weight_branch.empty() || !mcidbranch.empty() || !mc_weight_branch.empty()){ + ERROR("Vectorized version currently not supported when adding extra branches"); + return 1; + } +#endif + #ifdef _OPENMP unsigned int concurentThreadsSupported = std::thread::hardware_concurrency(); unsigned int nThreads = NamedParameter( "nCores", concurentThreadsSupported ); diff --git a/src/Minimiser.cpp b/src/Minimiser.cpp index 0eaabb29f01..b28f69fcaa5 100644 --- a/src/Minimiser.cpp +++ b/src/Minimiser.cpp @@ -74,12 +74,12 @@ void Minimiser::prepare() m_minimiser->SetPrintLevel( m_printLevel ); m_mapping.clear(); m_covMatrix.clear(); - for(size_t i = 0 ; i < m_parSet->size(); ++i) + for(size_t i = 0 ; i < m_parSet->size(); ++i) { auto par = m_parSet->at(i); if ( ! par->isFree() ) continue; m_minimiser->SetVariable(m_mapping.size(), par->name(), par->mean(), par->stepInit()); - if ( par->minInit() != 0 || par->maxInit() != 0 ) + if ( par->minInit() != 0 || par->maxInit() != 0 ) m_minimiser->SetVariableLimits( m_mapping.size(), par->minInit(), par->maxInit() ); m_mapping.push_back(i); if ( m_printLevel != 0 ) INFO( *par ); @@ -107,23 +107,23 @@ bool Minimiser::doFit() for ( unsigned int j = 0; j < m_nParams; ++j ) { m_covMatrix[i + m_nParams * j] = m_minimiser->CovMatrix( i, j ); } - } - m_status = m_minimiser->Status(); - /* - for( unsigned i = 0 ; i != m_nParams; ++i ){ - double low = 0; - double high = 0; - int status = 0; - m_minimiser->GetMinosError(i, low, high, status); - auto param = m_parSet->at( m_mapping[i] ); - param->setResult( *param, param->err(), low, high ); } - for( unsigned i = 0 ; i != m_nParams; ++i ) - { - auto param = m_parSet->at( m_mapping[i] ); - INFO( param->name() << " " << param->mean() << " " << param->errPos() << " " << param->errNeg() ); + m_status = m_minimiser->Status(); + if(NamedParameter("Minimiser::RunMinos",false)){ + for( unsigned i = 0 ; i != m_nParams; ++i ){ + double low = 0; + double high = 0; + int status = 0; + m_minimiser->GetMinosError(i, low, high, status); + auto param = m_parSet->at( m_mapping[i] ); + param->setResult( *param, param->err(), low, high ); + } + for( unsigned i = 0 ; i != m_nParams; ++i ) + { + auto param = m_parSet->at( m_mapping[i] ); + INFO( param->name() << " " << param->mean() << " " << param->errPos() << " " << param->errNeg() ); + } } - */ return 1; } @@ -168,8 +168,8 @@ TMatrixTSym Minimiser::covMatrixFull() const MinuitParameterSet* Minimiser::parSet() const { return m_parSet; } void Minimiser::addExtendedTerm( IExtendLikelihood* m_term ) -{ - m_extendedTerms.push_back( m_term ); +{ + m_extendedTerms.push_back( m_term ); } ROOT::Minuit2::Minuit2Minimizer* Minimiser::minimiserInternal() { return m_minimiser; } From da730a7868c346b5bd4c426f42b9bf558054d340 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 11 Aug 2020 11:59:01 +0200 Subject: [PATCH 224/250] fix enum parser --- AmpGen/enum.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/AmpGen/enum.h b/AmpGen/enum.h index 22abf25ba28..62c745030d6 100644 --- a/AmpGen/enum.h +++ b/AmpGen/enum.h @@ -39,13 +39,14 @@ namespace AmpGen { for( size_t x = 0; x != nChar ; ++x) if( word[x] != otherWord[x] ) return false; return true; }; - for( ; args[begin] != '\0' ; begin++ ) + while( args[begin] != '\0' ) { while( args[begin] == ' ' ) begin++; for( end=begin; args[end] != '\0'; end++ ) if( args[end] == ',' ) break; - if( compare( word.c_str(), args + begin , end-begin ) ) break; - begin = end; - counter++; + if( compare( word.c_str(), args + begin , end-begin ) ) break; + begin = end+1; + counter++; + if( args[end] == '\0' ) break; } if( args[begin] == '\0' ) return T(counter-1); return T(counter); From 14a8c123025daf9bb64cbfa7151ec5564d038fc5 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 11 Aug 2020 12:15:48 +0200 Subject: [PATCH 225/250] fix enum --- AmpGen/enum.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AmpGen/enum.h b/AmpGen/enum.h index 62c745030d6..9ffe2ad052f 100644 --- a/AmpGen/enum.h +++ b/AmpGen/enum.h @@ -48,7 +48,7 @@ namespace AmpGen { counter++; if( args[end] == '\0' ) break; } - if( args[begin] == '\0' ) return T(counter-1); + if( args[end] == '\0' ) return T(counter-1); return T(counter); } template std::string to_string(const T& enumItem, const char* args) From d26f957c25057de2de531cd81e596a040b5533a1 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 12 Aug 2020 09:47:06 +0200 Subject: [PATCH 226/250] fix enum... again ... and add unit tests this time --- AmpGen/MinuitParameter.h | 2 +- AmpGen/enum.h | 10 ++++++---- src/AmplitudeRules.cpp | 9 ++++++--- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/AmpGen/MinuitParameter.h b/AmpGen/MinuitParameter.h index 197f660ffb2..7d79369bd0d 100644 --- a/AmpGen/MinuitParameter.h +++ b/AmpGen/MinuitParameter.h @@ -10,7 +10,7 @@ namespace AmpGen { class MinuitParameterSet; - declare_enum( Flag, Free, Hide, Fix, CompileTimeConstant, Invalid ) + declare_enum( Flag, Free, Hide, Fix, CompileTimeConstant) class MinuitParameter { public: diff --git a/AmpGen/enum.h b/AmpGen/enum.h index 9ffe2ad052f..ba526c714b1 100644 --- a/AmpGen/enum.h +++ b/AmpGen/enum.h @@ -1,9 +1,10 @@ #ifndef AMPGEN_ENUM_H #define AMPGEN_ENUM_H 1 #include "AmpGen/MsgService.h" +#include "AmpGen/Utilities.h" #define declare_enum(name, ...) \ -enum class name {__VA_ARGS__}; \ +enum class name {__VA_ARGS__, Invalid}; \ template <> name parse(const std::string& word); \ template <> std::string to_string( const name& enumItem ); \ std::ostream& operator<<( std::ostream& os, const name& np); @@ -15,7 +16,7 @@ template <> name lexical_cast(const std::string& word, bool& /*status*/){ return std::ostream& operator<<(std::ostream& os, const name& np){ return os << to_string(np);} #define make_enum(name, ...) \ -enum class name {__VA_ARGS__}; \ +enum class name {__VA_ARGS__, Invalid}; \ template <> name parse(const std::string& word){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::parse(word, args); } \ template <> std::string to_string( const name& enumItem ){ constexpr auto args = #__VA_ARGS__; return AmpGen::detail::to_string(enumItem, args) ; } \ template <> name lexical_cast(const std::string& word, bool& /*status*/){ return parse(word); } \ @@ -39,16 +40,17 @@ namespace AmpGen { for( size_t x = 0; x != nChar ; ++x) if( word[x] != otherWord[x] ) return false; return true; }; + bool found = false; while( args[begin] != '\0' ) { while( args[begin] == ' ' ) begin++; for( end=begin; args[end] != '\0'; end++ ) if( args[end] == ',' ) break; - if( compare( word.c_str(), args + begin , end-begin ) ) break; + if( compare( word.c_str(), args + begin , end-begin ) ) { found = true; break; } begin = end+1; counter++; if( args[end] == '\0' ) break; } - if( args[end] == '\0' ) return T(counter-1); + if(!found) return T::Invalid; return T(counter); } template std::string to_string(const T& enumItem, const char* args) diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index b7a3a10e452..cabb04e1b49 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -34,14 +34,17 @@ Coupling::Coupling(MinuitParameter* re, MinuitParameter* im) : } m_particle = Particle(m_name); coordinateType coord = NamedParameter("CouplingConstant::Coordinates", coordinateType::cartesian); - angType degOrRad = NamedParameter("CouplingConstant::AngularUnits", angType::rad); + angType degOrRad = NamedParameter("CouplingConstant::AngularUnits" , angType::rad); m_isCartesian = true; + if( coord == coordinateType::polar ) m_isCartesian = false; - else if ( coord != coordinateType::cartesian){ + + if ( coord == coordinateType::Invalid){ FATAL("Coordinates for coupling constants must be either cartesian or polar"); } if ( degOrRad == angType::deg) m_sf = M_PI / 180; - else if ( degOrRad != angType::rad){ + + if ( degOrRad == angType::Invalid ){ FATAL("TotalCoupling::AngularUnits must be either rad or deg"); } } From 24d7015d872cc4ebd0b74739f359db904bd97068 Mon Sep 17 00:00:00 2001 From: mstahl Date: Wed, 12 Aug 2020 10:45:31 +0200 Subject: [PATCH 227/250] [Particle tables] update particle tables to be compatible with Gauss --- options/MintDalitzSpecialParticles.csv | 4 +++- options/mass_width.csv | 16 ++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/options/MintDalitzSpecialParticles.csv b/options/MintDalitzSpecialParticles.csv index 9ed8bdb1b0f..6565871935b 100644 --- a/options/MintDalitzSpecialParticles.csv +++ b/options/MintDalitzSpecialParticles.csv @@ -48,5 +48,7 @@ 1.86484E+03 ,1.7E-01,1.7E-01,1.605E-09 ,6.0E-12,6.0E-12,1/2, ,0 ,-, ,F, 998421, 0, ,R,D~ ,cU 3.8948E+03 ,1.1E-02,1.1E-02,2.96E+00 ,2.1E-03,2.1E-03,1 ,+,1 ,+,-, , 999443, 0, ,R,Z(c)(3900) ,cCuU 3.8948E+03 ,1.1E-02,1.1E-02,2.96E+00 ,2.1E-03,2.1E-03,1 ,+,1 ,+,-, , 999444, +, ,R,Z(c)(3900) ,cCuD -9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1/2,+,0 ,+,+,F, 998140, 0, ,R,XiPi0 ,?? +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1 , ,1/2 ,-, ,F, , 0,3,R,LambdaEta ,uds +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1/2, ,1/2 ,-, ,F, , -,3,R,XiPi ,dss +9.990E+03 ,1.0E+01,1.0E+01,9.9E+09 ,3.0E+01,3.0E+01,1/2, ,1/2 ,-, ,F, , 0,3,R,XiPi ,uss *** diff --git a/options/mass_width.csv b/options/mass_width.csv index 4833cbc1c7e..122d5fec4a0 100644 --- a/options/mass_width.csv +++ b/options/mass_width.csv @@ -666,16 +666,16 @@ 1.32171E+03 ,7.0E-02,7.0E-02,4.04E-12 ,4.0E-14,4.0E-14,1/2, ,1/2 ,+, ,F, 3312, -,4,R,Xi ,dss 1.53180E+03 ,3.2E-01,3.2E-01,9.1E+00 ,5.0E-01,5.0E-01,1/2, ,3/2 ,+, ,F, 3324, 0,4,R,Xi(1530) ,uss 1.5350E+03 ,6.0E-01,6.0E-01,9.9E+00 ,1.7E+00,1.9E+00,1/2, ,3/2 ,+, ,F, 3314, -,4,R,Xi(1530) ,dss -1.6240E+03 ,3.0E+00,3.0E+00,22.5 ,-1 ,-1 ,1/2, ,3/2 ,+, ,F, , 0,1,S,Xi(1620) ,uss -1.6240E+03 ,3.0E+00,3.0E+00,22.5 ,-1 ,-1 ,1/2, ,3/2 ,+, ,F, , -,1,S,Xi(1620) ,dss -1.6900E+03 ,1.0E+01,1.0E+01,-1 ,-1 ,-1 ,1/2, ,? ,?, ,F, , 0,3,D,Xi(1690) ,uss -1.6900E+03 ,1.0E+01,1.0E+01,-1 ,-1 ,-1 ,1/2, ,? ,?, ,F, , -,3,D,Xi(1690) ,dss +1.6240E+03 ,3.0E+00,3.0E+00,22.5 ,-1 ,-1 ,1/2, ,1/2 ,-, ,F, , 0,1,S,Xi(1620) ,uss +1.6240E+03 ,3.0E+00,3.0E+00,22.5 ,-1 ,-1 ,1/2, ,1/2 ,-, ,F, , -,1,S,Xi(1620) ,dss +1.6900E+03 ,1.0E+01,1.0E+01,-1 ,-1 ,-1 ,1/2, ,1/2 ,-, ,F, , 0,3,D,Xi(1690) ,uss +1.6900E+03 ,1.0E+01,1.0E+01,-1 ,-1 ,-1 ,1/2, ,1/2 ,-, ,F, , -,3,D,Xi(1690) ,dss 1.823E+03 ,5.0E+00,5.0E+00,2.40E+01 ,1.5E+01,1.0E+01,1/2, ,3/2 ,-, ,F, 13324, 0,3,D,Xi(1820) ,uss 1.823E+03 ,5.0E+00,5.0E+00,2.40E+01 ,1.5E+01,1.0E+01,1/2, ,3/2 ,-, ,F, 13314, -,3,D,Xi(1820) ,dss -1.950E+03 ,1.5E+01,1.5E+01,6.0E+01 ,2.0E+01,2.0E+01,1/2, ,? ,?, ,F, , 0,3,D,Xi(1950) ,uss -1.950E+03 ,1.5E+01,1.5E+01,6.0E+01 ,2.0E+01,2.0E+01,1/2, ,? ,?, ,F, , -,3,D,Xi(1950) ,dss -2.025E+03 ,5.0E+00,5.0E+00,2.0E+01 ,1.5E+01,5.0E+00,1/2, ,>3/2,?, ,F, , 0,3,D,Xi(2030) ,uss -2.025E+03 ,5.0E+00,5.0E+00,2.0E+01 ,1.5E+01,5.0E+00,1/2, ,>3/2,?, ,F, , -,3,D,Xi(2030) ,dss +1.950E+03 ,1.5E+01,1.5E+01,6.0E+01 ,2.0E+01,2.0E+01,1/2, ,5/2 ,-, ,F, , 0,3,D,Xi(1950) ,uss +1.950E+03 ,1.5E+01,1.5E+01,6.0E+01 ,2.0E+01,2.0E+01,1/2, ,5/2 ,-, ,F, , -,3,D,Xi(1950) ,dss +2.025E+03 ,5.0E+00,5.0E+00,2.0E+01 ,1.5E+01,5.0E+00,1/2, ,3/2 ,+, ,F, , 0,3,D,Xi(2030) ,uss +2.025E+03 ,5.0E+00,5.0E+00,2.0E+01 ,1.5E+01,5.0E+00,1/2, ,3/2 ,+, ,F, , -,3,D,Xi(2030) ,dss 2.137E+03 ,4.0E+00,4.0E+00,20 ,-1 ,-1 ,1/2, ,? ,?, ,F, , 0,1,S,Xi(2120) ,uss 2.137E+03 ,4.0E+00,4.0E+00,20 ,-1 ,-1 ,1/2, ,? ,?, ,F, , -,1,S,Xi(2120) ,dss 2.189E+03 ,7.0E+00,7.0E+00,4.6E+01 ,2.7E+01,2.7E+01,1/2, ,? ,?, ,F, , 0,2,S,Xi(2250) ,uss From 7b5d15a89a19ed5cd9031dcb77fa3e12bb58e796 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 13 Aug 2020 15:04:17 +0200 Subject: [PATCH 228/250] add automated testing against released models --- AmpGen/NamedParameter.h | 17 +++-- AmpGen/Particle.h | 16 +++-- apps/ConvertToSourceCode.cpp | 1 - apps/Generator.cpp | 12 ++-- apps/lib_diff.cpp | 121 ++++++++++++++++++++++++++++++++++ doc/release.notes | 1 + options/run_lbAmpGen_tests.sh | 22 +++++++ src/NamedParameter.cpp | 9 --- test/test_enum.cpp | 22 +++++++ 9 files changed, 194 insertions(+), 27 deletions(-) create mode 100644 apps/lib_diff.cpp create mode 100755 options/run_lbAmpGen_tests.sh create mode 100644 test/test_enum.cpp diff --git a/AmpGen/NamedParameter.h b/AmpGen/NamedParameter.h index 40774b215fb..8c5a1264385 100644 --- a/AmpGen/NamedParameter.h +++ b/AmpGen/NamedParameter.h @@ -12,6 +12,7 @@ #include #include #include +#include #include "AmpGen/MsgService.h" #include "AmpGen/OptionsParser.h" @@ -74,7 +75,6 @@ namespace AmpGen setFromOptionsParser(); if ( OptionsParser::printHelp() ) help( defVec.size() > 0 ? defVec[0] : T() ); } -// ~NamedParameter(){ INFO("Deconstructing: " << m_name ); } void help(const T& def){ std::string type = type_string(); if( type == "std::__cxx11::basic_string, std::allocator >" ) type = "string"; @@ -148,9 +148,8 @@ namespace AmpGen return return_container; } }; - template std::ostream& operator<<( std::ostream& os, const NamedParameter& np ); - - std::string optionalHelpString(const std::string& header, const std::vector>& args); + template std::ostream& operator<<( std::ostream& os, const NamedParameter& np ); + template std::string optionalHelpString(const std::string& header, const T&... args); } template @@ -165,4 +164,14 @@ std::ostream& AmpGen::operator<<( std::ostream& os, const AmpGen::NamedParameter return os; } +template std::string AmpGen::optionalHelpString(const std::string& header, const T&... args ) +{ + std::stringstream rt; + rt << header; + for_each( std::make_tuple(args...), [&rt](const auto& f) mutable { + rt << "\n\033[3m " << f.first << "\033[0m: " << f.second; + }); + return rt.str(); +} + #endif diff --git a/AmpGen/Particle.h b/AmpGen/Particle.h index 593fc2663b5..4b9fc065585 100644 --- a/AmpGen/Particle.h +++ b/AmpGen/Particle.h @@ -299,13 +299,15 @@ namespace AmpGen std::string modifierString() const; ///< Re-generate modifier string used to create particle void sortDaughters(); ///< Recursively order the particle's decay products. - NamedParameter m_spinFormalism = {"Particle::SpinFormalism" ,spinFormalism::Covariant, optionalHelpString("Formalism to use for spin calculations", { - {"Covariant", "[default] Covariant Tensor, based on Rarita-Schwinger constraints on the allowed covariant wavefunctions."} - , {"Canonical", "Canonical formulation, based on rotational properties of wavefunctions, i.e. Wigner D-matrices and Clebsch-Gordan for (L,S) expansion."} } ) }; - - NamedParameter m_spinBasis = {"Particle::SpinBasis", spinBasis::Dirac, optionalHelpString("Basis to use for calculating external polarisation tensors / spinors.", { - {"Dirac", "[default] Quantises along the z-axis"} - , {"Weyl" , "Quantises along the direction of motion"}} )}; + NamedParameter m_spinFormalism = {"Particle::SpinFormalism" ,spinFormalism::Covariant, + optionalHelpString("Formalism to use for spin calculations", + std::make_pair("Covariant", "[default] Covariant Tensor, based on Rarita-Schwinger constraints on the allowed covariant wavefunctions.") + , std::make_pair("Canonical", "Canonical formulation, based on rotational properties of wavefunctions, i.e. Wigner D-matrices and Clebsch-Gordan for (L,S) expansion.") ) }; + + NamedParameter m_spinBasis = {"Particle::SpinBasis", spinBasis::Dirac, + optionalHelpString("Basis to use for calculating external polarisation tensors / spinors.", + std::make_pair("Dirac", "[default] Quantises along the z-axis") + , std::make_pair("Weyl", "Quantises along the direction of motion") )}; NamedParameter m_defaultModifier = {"Particle::DefaultModifier","", "Default modifier to use for lineshapes, for example to use normalised vs unnormalised Blatt-Weisskopf factors."}; }; std::ostream& operator<<( std::ostream& os, const Particle& particle ); diff --git a/apps/ConvertToSourceCode.cpp b/apps/ConvertToSourceCode.cpp index e1695ff454c..43b77c0048c 100644 --- a/apps/ConvertToSourceCode.cpp +++ b/apps/ConvertToSourceCode.cpp @@ -80,7 +80,6 @@ template void generate_source(T& pdf, const std::string& sourceFile, M auto oEventType = NamedParameter("EventType").getVector(); TRandom3 rnd(seed); - INFO("First random number = " << rnd.Uniform() ); EventType eventType( oEventType ); Generator phsp(eventType); diff --git a/apps/Generator.cpp b/apps/Generator.cpp index 612cbfed422..3b79639481b 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -146,13 +146,13 @@ int main( int argc, char** argv ) int seed = NamedParameter ("Seed" , 0, "Random seed used in event Generation" ); std::string outfile = NamedParameter("Output" , "Generate_Output.root" , "Name of output file" ); auto pdfType = NamedParameter( "Type", pdfTypes::CoherentSum, optionalHelpString("Type of PDF to use:", - { {"CoherentSum" , "Describes decays of a (pseudo)scalar particle to N pseudoscalars"} - , {"PolarisedSum" , "Describes the decay of a particle with spin to N particles carrying spin."} - , {"FixedLib" , "PDF to describe a decay from a precompiled library, such as those provided to GAUSS."}} ) ); + std::make_pair(pdfTypes::CoherentSum , "Describes decays of a (pseudo)scalar particle to N pseudoscalars") + , std::make_pair(pdfTypes::PolarisedSum, "Describes the decay of a particle with spin to N particles carrying spin.") + , std::make_pair(pdfTypes::FixedLib , "PDF to describe a decay from a precompiled library, such as those provided to GAUSS.") ) ); auto phspType = NamedParameter( "PhaseSpace", phspTypes::PhaseSpace, optionalHelpString("Phase-space generator to use:", - { {"PhaseSpace" , "Phase space generation based on Raubold-Lynchi algorithm (recommended)."} - , {"TreePhaseSpace" , "Divides the phase-space into a series of quasi two-body phase-spaces for efficiently generating narrow states."} - , {"RecursivePhaseSpace", "Includes possible quasi-stable particles and the phase spaces of their decay products, such as Λ baryons."}} ) ); + std::make_pair(phspTypes::PhaseSpace , "Phase space generation based on Raubold-Lynch algorithm (recommended).\0") + , std::make_pair(phspTypes::TreePhaseSpace , "Divides the phase-space into a series of quasi two-body phase-spaces for efficiently generating narrow states.\0") + , std::make_pair(phspTypes::RecursivePhaseSpace, "Includes possible quasi-stable particles and the phase spaces of their decay products, such as Λ baryons.\0") ) ); std::string lib = NamedParameter("Library","","Name of library to use for a fixed library generation"); size_t nBins = NamedParameter ("nBins" ,100, "Number of bins for monitoring plots." ); diff --git a/apps/lib_diff.cpp b/apps/lib_diff.cpp new file mode 100644 index 00000000000..344f87b20ea --- /dev/null +++ b/apps/lib_diff.cpp @@ -0,0 +1,121 @@ +#include "AmpGen/PhaseSpace.h" +#include "AmpGen/DynamicFCN.h" +#include "AmpGen/Utilities.h" +#include "AmpGen/OptionsParser.h" +#include "AmpGen/NamedParameter.h" + +using namespace AmpGen; + +std::vector cmd( const std::string& command ){ + std::vector output; + FILE* proc = popen(command.c_str(), "r"); + char buf[4096]; + while (!feof(proc) && fgets(buf, sizeof(buf), proc)) output.push_back(buf); + pclose(proc); + return output; +} + +struct Counter { + int pass {0}; + int total{0}; + Counter() = default; + Counter( const bool& pass ) : pass(pass), total(1) {} + Counter( const double& a, const double& b, const std::string& name, const double& tolerance ); + Counter( const complex_t& a, const complex_t& b, const std::string& name, const double& tolerance ); + Counter(const std::vector& a, const std::vector& b, const std::string& name, const double& tolerance); + void operator+=( const Counter& other ) + { + this->pass += other.pass; + this->total += other.total; + } + +}; + +Counter::Counter(const double& a, const double& b, const std::string& name, const double& tolerance) +{ + double diff = std::abs(a-b); + total = 1; + if( diff > std::abs(tolerance) ){ + ERROR( name << " (" << a << " " << b << ") = " << diff << " > " << tolerance); + pass = 0; + } + else pass =1; + DEBUG( name << " (" << a << " " << b << ") = " << diff << " > " << tolerance); +} + +Counter::Counter(const complex_t& a, const complex_t& b, const std::string& name, const double& tolerance) +{ + double diff_re = std::abs(std::real(a)-std::real(b)); + double diff_im = std::abs(std::imag(a)-std::imag(b)); + total =1; + if( diff_re > std::abs(tolerance) || diff_im > std::abs(tolerance) ){ + ERROR( name << " (" << a << " " << b << ") = " << diff_re << ", " << diff_im << " > " << tolerance); + pass =0; + } + else pass = 1; + DEBUG( name << " (" << a << " " << b << ") = " << diff_re << ", " << diff_im << " < " << tolerance); +} + +Counter::Counter(const std::vector& a, const std::vector& b, const std::string& name, const double& tolerance) +{ + total = a.size(); + for( size_t i = 0 ; i < a.size(); ++i ){ + double diff_re = std::abs(std::real(a[i])-std::real(b[i])); + double diff_im = std::abs(std::imag(a[i])-std::imag(b[i])); + if( diff_re > std::abs(tolerance) || diff_im > std::abs(tolerance) ){ + ERROR( name << " (" << a[i] << " " << b[i] << ") = " << diff_re << ", " << diff_im << " > " << tolerance); + } + else pass++; + DEBUG( name << " (" << a[i] << " " << b[i] << ") = " << diff_re << ", " << diff_im << " > " << tolerance); + } +} + +int main( int argc, char** argv ) +{ + std::string modelName = argv[1]; + OptionsParser::getMe()->setQuiet(); + OptionsParser::setArgs( argc, argv ); + PhaseSpace phsp( EventType(NamedParameter("EventType", "").getVector()) ); + auto event = phsp.makeEvent(); + auto event2 = phsp.makeEvent(); + std::string lib = NamedParameter("Lib",""); + std::string refLib = NamedParameter("RefLib",""); + std::string type = NamedParameter("Type","CoherentSum"); + Counter total; + + auto ftable = cmd("nm " + refLib + "| grep __wParams"); + if( type == "CoherentSum"){ + auto f1 = DynamicFCN(lib, "AMP"); + auto f2 = DynamicFCN(refLib, "AMP"); + total += Counter(f1(event,+1), f2(event,+1), modelName + " fcn(x)", 10e-6 ); + total += Counter(f1(event,-1), f2(event,-1), modelName + " fcn(Px)", 10e-6); + for( auto& line : ftable ) + { + auto i = trim( split(line,' ')[2] ); + auto f = DynamicFCN(lib, i ); + auto g = DynamicFCN(refLib, i ); + if( !f.isLinked() || !g.isLinked() ) total += false ; + else total += Counter( f(event), g(event), i, 10e-6); + } + } + if( type == "PolarisedSum"){ + auto f1 = DynamicFCN(lib , "FCN_extPol"); + auto f2 = DynamicFCN(refLib, "FCN_extPol"); + total += Counter(f1(event,+1,0,0,0), f2(event,+1,0,0,0), modelName + " fcn(x)" , 1e-6); + total += Counter(f1(event,-1,0,0,0), f2(event,-1,0,0,0), modelName + " fcn(Px)", 1e-6); + for( auto& line : ftable ){ + auto i = trim( split(line,' ')[2] ); + auto a1 = DynamicFCN(const double*)>(lib , i ); + auto a2 = DynamicFCN(const double*)>(refLib, i ); + if( ! a1.isLinked() || ! a2.isLinked() ) total += false; + else { + auto pass = Counter(a1(event), a2(event), i, 10e-6); + total += pass; + } + } + } + if(total.pass == total.total) + INFO("Library: " << modelName << " matches [passed = " << total.pass << " / " << total.total << "]" ); + else + ERROR("Library: " << modelName << " does not match [passed = " << total.pass << " / " << total.total << "]" ); +} diff --git a/doc/release.notes b/doc/release.notes index 6b1c47a5a5d..cc2cb56fdc8 100644 --- a/doc/release.notes +++ b/doc/release.notes @@ -8,6 +8,7 @@ - Support for AVX2 for amplitude evaluation / integration single/double precision. - Updated plotting for making component amplitude plots. - Better thread safety of integration should improve fit stability. + - Add GenericKmatrix lineshape for handling ... Generic K-matrices (L=0 only) !=================== AmpGen v1r2 2019-11-12 ================== - New phase space Generator TreePhaseSpace for producing narrow resonances. - Improved handling of CP conjugated amplitudes. diff --git a/options/run_lbAmpGen_tests.sh b/options/run_lbAmpGen_tests.sh new file mode 100755 index 00000000000..0e1ea585131 --- /dev/null +++ b/options/run_lbAmpGen_tests.sh @@ -0,0 +1,22 @@ +branch=mstahl_AmpGen + +tmp_dir=$(mktemp -d -t ci-XXXXXXXXXX) +echo "TMPDIR=$tmp_dir" +cd $tmp_dir + +wget https://gitlab.cern.ch/lhcb/Gauss/-/archive/$branch/Gauss-${branch}.zip?path=Gen/LbAmpGen -O LbAmpGen.zip >> /dev/null +unzip LbAmpGen.zip >> /dev/null +top=Gauss-$branch-Gen-LbAmpGen + +for model in $top/Gen/LbAmpGen/models/*.opt ; do + filename=$(basename $model) + without_ext=${filename%.*} + if [ $without_ext == "DtoKpipipi_v1" ] || + [ $without_ext == "DtopiKpipi_v1" ] || + [ $without_ext == "DtoKKpipi_v1" ] ; then continue ; fi # these are old models that kept for backwards compatability, dont expect to be able reproduce exactly + mkdir -p build/$without_ext + $AMPGENROOT/build/bin/ConvertToSourceCode $model --Output build/$without_ext/new.cpp >> /dev/null + g++ -Ofast -shared -rdynamic --std=c++11 -fPIC build/$without_ext/new.cpp -o build/$without_ext/new.so + g++ -Ofast -shared -rdynamic --std=c++11 -fPIC $top/Gen/LbAmpGen/src/${without_ext}.cpp -o build/$without_ext/gaussUpdate.so + $AMPGENROOT/build/bin/lib_diff $model --Lib=build/$without_ext/new.so --RefLib=build/$without_ext/gaussUpdate.so +done diff --git a/src/NamedParameter.cpp b/src/NamedParameter.cpp index a2b7ef86db8..282581e3b75 100644 --- a/src/NamedParameter.cpp +++ b/src/NamedParameter.cpp @@ -11,12 +11,3 @@ template class AmpGen::NamedParameter; template class AmpGen::NamedParameter; template class AmpGen::NamedParameter; -std::string AmpGen::optionalHelpString(const std::string& header, const std::vector>& args ) -{ - std::string rt=header +"\n"; - for( size_t i = 0 ; i < args.size(); ++i ){ - rt += "\033[3m " + args[i].first + std::string( 25 - args[i].first.size(), ' '); - rt += "\033[0m: " + args[i].second + (i==args.size()-1 ? "" : "\n" ); - } - return rt; -} diff --git a/test/test_enum.cpp b/test/test_enum.cpp new file mode 100644 index 00000000000..2a3c492c275 --- /dev/null +++ b/test/test_enum.cpp @@ -0,0 +1,22 @@ + +#define BOOST_TEST_DYN_LINK + +#define BOOST_TEST_MODULE "enum" + +#include +namespace utf = boost::unit_test; + +#include "AmpGen/enum.h" + +namespace AmpGen { + make_enum( test_enum, state1, state2, state3 ) +} +using namespace AmpGen; + +BOOST_AUTO_TEST_CASE( test_enums ) +{ + BOOST_CHECK( parse ("state1") == test_enum::state1 ); + BOOST_CHECK( parse ("state2") == test_enum::state2 ); + BOOST_CHECK( parse ("state3") == test_enum::state3 ); + BOOST_CHECK( parse ("blag") == test_enum::Invalid ); +} From c845a5f27a9b308785f26ca7b31e478097e946ed Mon Sep 17 00:00:00 2001 From: phdargen Date: Thu, 20 Aug 2020 20:02:19 +0200 Subject: [PATCH 229/250] added spin factors for V[S,P]->V V decays --- AmpGen/Vertex.h | 5 +++++ src/Vertex.cpp | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/AmpGen/Vertex.h b/AmpGen/Vertex.h index d7856891272..b78b8a7def8 100644 --- a/AmpGen/Vertex.h +++ b/AmpGen/Vertex.h @@ -119,6 +119,11 @@ namespace AmpGen DECLARE_VERTEX( V_VS_D ); DECLARE_VERTEX( V_TS_P ); DECLARE_VERTEX( V_TS_D ); + + DECLARE_VERTEX( V_VV_P ); + DECLARE_VERTEX( V_VV_P1 ); + DECLARE_VERTEX( V_VV_P2 ); + DECLARE_VERTEX( V_VV_S ); DECLARE_VERTEX( T_VS_D ); DECLARE_VERTEX( T_VS_P ); diff --git a/src/Vertex.cpp b/src/Vertex.cpp index f86045f0604..d96c0cd6955 100644 --- a/src/Vertex.cpp +++ b/src/Vertex.cpp @@ -178,6 +178,40 @@ DEFINE_VERTEX( V_VS_D ) return ( Sv( mu, nu ) * L_2_V0( -nu, -alpha ) * V1( alpha ) ) * V2[0]; } +DEFINE_VERTEX( V_VV_P ) +{ + Tensor L = Orbital_PWave( P, Q )/GeV; + return L(mu) * dot(V1,V2); +} + +DEFINE_VERTEX( V_VV_P1 ) +{ + Tensor L = Orbital_PWave( P, Q )/GeV; + Tensor Sv = Spin1Projector( P ); + Tensor term = LeviCivita()( -mu, -nu, -alpha, -beta ) * P( nu )/GeV * V1( alpha ) * V2( beta ); + Tensor phi_1 = term(-mu) * Sv(mu,nu); + + return LeviCivita()( -mu, -nu, -alpha, -beta ) * P( mu )/GeV * L(nu) * phi_1(alpha); +} + +DEFINE_VERTEX( V_VV_P2 ) +{ + Tensor L = Orbital_PWave( P, Q )/GeV; + Tensor Sv = Spin2Projector( P ); + Tensor phi_2 = Sv(-mu,-nu,alpha,beta) * V1(mu) * V2(nu); + + return L(-mu) * phi_2(mu,nu); +} + +DEFINE_VERTEX( V_VV_S ) +{ + Tensor Sv = Spin1Projector( P ); + Tensor term = LeviCivita()( -mu, -nu, -alpha, -beta ) * P( nu )/GeV * V1( alpha ) * V2( beta ); + + return term( -mu ) * Sv(mu, nu); +} + + DEFINE_VERTEX( T_VS_D ) { Tensor G = LeviCivita()( -mu, -nu, -alpha, -beta ) * P( nu ) * Q( alpha ) * V1( beta ); From d2ff8306673d2ae991ef1227a7a09fccc6eb74ff Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 22 Sep 2020 10:01:30 +0200 Subject: [PATCH 230/250] Add LambdaExpression for expressions that dynamically depend on the value of some arbitrary C++ code --- AmpGen/ASTResolver.h | 1 + AmpGen/CacheTransfer.h | 42 ++++++++++++++++++++++++++-------------- AmpGen/Expression.h | 18 ++++++++++++++++- src/ASTResolver.cpp | 8 +++++++- src/CacheTransfer.cpp | 18 +++++++++++++++++ src/Expression.cpp | 19 +++++++++++++++++- test/test_Expression.cpp | 15 +++++++++++++- 7 files changed, 103 insertions(+), 18 deletions(-) diff --git a/AmpGen/ASTResolver.h b/AmpGen/ASTResolver.h index 1a29a215a47..1fc44234816 100644 --- a/AmpGen/ASTResolver.h +++ b/AmpGen/ASTResolver.h @@ -72,4 +72,5 @@ namespace AmpGen { template <> void ASTResolver::resolve ( const SubTree & obj ); template <> void ASTResolver::resolve ( const Spline & obj ); template <> void ASTResolver::resolve( const MinuitParameterLink& obj ); + template <> void ASTResolver::resolve( const LambdaExpression& obj); } diff --git a/AmpGen/CacheTransfer.h b/AmpGen/CacheTransfer.h index 4a2748e60dc..67bcd1e0f95 100644 --- a/AmpGen/CacheTransfer.h +++ b/AmpGen/CacheTransfer.h @@ -4,11 +4,13 @@ #include #include #include +#include namespace AmpGen { class CompiledExpressionBase; class MinuitParameter; + class LambdaExpression; class CacheTransfer { @@ -16,13 +18,13 @@ namespace AmpGen CacheTransfer(); CacheTransfer( const size_t& address, const std::string& name, const double& value=0, const size_t& size=1); virtual ~CacheTransfer() = default; - + size_t address() const { return m_address ; } - + virtual void transfer( CompiledExpressionBase* destination ); virtual void print() const; virtual size_t size() const { return m_size ; } - + protected: size_t m_address = {0}; size_t m_size = {0}; @@ -32,17 +34,29 @@ namespace AmpGen class ParameterTransfer : public CacheTransfer { - public: - ParameterTransfer( const size_t& address, const std::string& name, AmpGen::MinuitParameter* source ); - virtual ~ParameterTransfer() = default; - - size_t size() const override { return 1 ; } - - void transfer( CompiledExpressionBase* destination ) override; - void print() const override; - - protected: - MinuitParameter* m_source = {nullptr}; + public: + ParameterTransfer( const size_t& address, const std::string& name, MinuitParameter* source ); + virtual ~ParameterTransfer() = default; + + size_t size() const override { return 1 ; } + + void transfer( CompiledExpressionBase* destination ) override; + void print() const override; + + protected: + MinuitParameter* m_source = {nullptr}; + }; + class LambdaTransfer : public CacheTransfer + { + public: + LambdaTransfer( const size_t& address, const std::string& name, const LambdaExpression* source ); + + size_t size() const override { return 1 ; } + + void transfer( CompiledExpressionBase* destination ) override; + void print() const override; + + std::function m_function; }; } // namespace AmpGen diff --git a/AmpGen/Expression.h b/AmpGen/Expression.h index d40596edf48..ce83ed82765 100644 --- a/AmpGen/Expression.h +++ b/AmpGen/Expression.h @@ -194,6 +194,7 @@ namespace AmpGen double m_defaultValue; bool m_resolved; }; + class ComplexParameter : public IExpression { public: ComplexParameter( const Parameter& real, const Parameter& imag ); @@ -205,6 +206,19 @@ namespace AmpGen Parameter m_real; Parameter m_imag; }; + /** @ingroup ExpressionEngine class LambdaExpression + @brief Parameter that the value of which is given by some arbitrary C++ function + */ + class LambdaExpression : public IExpression { + public: + template + LambdaExpression( const function_type& function) : m_function(function) {} + std::string to_string(const ASTResolver* resolver = nullptr) const override; + void resolve( ASTResolver& resolver) const override; + operator Expression() const; + complex_t operator()() const override; + std::function m_function; + }; /** @ingroup ExpressionEngine class Ternary @brief Evaluates the ternary operator. @@ -213,12 +227,14 @@ namespace AmpGen \code{.cpp} return a ? b : c \endcode */ - struct Ternary : public IExpression { + class Ternary : public IExpression { + public: Ternary( const Expression& cond, const Expression& v1, const Expression& v2 ); std::string to_string(const ASTResolver* resolver = nullptr ) const override; void resolve( ASTResolver& resolver ) const override; operator Expression() const ; complex_t operator()() const override { return std::real(m_cond()) ? m_v1() : m_v2(); } + private: Expression m_cond; Expression m_v1; Expression m_v2; diff --git a/src/ASTResolver.cpp b/src/ASTResolver.cpp index 3b2b5bfe0b7..8d761727546 100644 --- a/src/ASTResolver.cpp +++ b/src/ASTResolver.cpp @@ -131,7 +131,13 @@ template <> void ASTResolver::resolve(const MinuitParameter if( m_mps == nullptr ) return; auto it = m_mps->find(parameter.name()); if( it == nullptr ) return; - addResolvedParameter(¶meter, addCacheFunction( parameter.name(),it)); + addResolvedParameter(¶meter, addCacheFunction(parameter.name(), it)); +} + +template <> void ASTResolver::resolve( const LambdaExpression& obj) +{ + if( m_resolvedParameters.count(&obj) != 0 ) return; + addResolvedParameter(&obj, addCacheFunction( "lxpr_" + std::to_string(m_nParameters), &obj)); } std::map> ASTResolver::cacheFunctions() const diff --git a/src/CacheTransfer.cpp b/src/CacheTransfer.cpp index 0963b0d305b..625ccc8ca1c 100644 --- a/src/CacheTransfer.cpp +++ b/src/CacheTransfer.cpp @@ -44,3 +44,21 @@ void ParameterTransfer::print() const { INFO( "Source: " << m_source->name() << " address = " << m_address << " value = " << m_source->mean() ); } + + +LambdaTransfer::LambdaTransfer(const size_t& address, const std::string& name, const LambdaExpression* source ) + : CacheTransfer(address, name, source->m_function(), 1), + m_function(source->m_function) +{ +} + +void LambdaTransfer::transfer( CompiledExpressionBase* destination ) +{ + destination->setExternal( m_function(), m_address ); +} + +void LambdaTransfer::print() const +{ + INFO( m_name << " = " << m_function() << " address = " << m_address ); +} + diff --git a/src/Expression.cpp b/src/Expression.cpp index 3ea94ad33de..db09f2283b3 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -26,6 +26,7 @@ DEFINE_CAST(SubTree ) DEFINE_CAST(Ternary ) DEFINE_CAST(Function ) DEFINE_CAST(ComplexParameter); +DEFINE_CAST(LambdaExpression); Expression::Expression( const std::shared_ptr& expression ) : m_expression( expression ) {} @@ -248,7 +249,6 @@ std::string SubTree::to_string(const ASTResolver* /*resolver*/) const void SubTree::resolve( ASTResolver& resolver ) const { resolver.resolve( *this ); - // m_expression.resolve( resolver ); } Expression AmpGen::make_cse( const Expression& A , bool simplify ) @@ -340,3 +340,20 @@ complex_t ComplexParameter::operator()() const { return m_real() + 1i * m_imag(); } + +std::string LambdaExpression::to_string(const ASTResolver* resolver) const +{ + if( resolver == nullptr ){ WARNING("Not clear what is is you're trying to do here"); return "";} return resolver->resolvedParameter(this); +} + +complex_t LambdaExpression::operator()() const +{ + return m_function(); +} + +void LambdaExpression::resolve(ASTResolver& resolver) const { + resolver.resolve(*this); +} + + + diff --git a/test/test_Expression.cpp b/test/test_Expression.cpp index 571d4e260c9..fed4fee9396 100644 --- a/test/test_Expression.cpp +++ b/test/test_Expression.cpp @@ -6,7 +6,8 @@ namespace utf = boost::unit_test; #include "AmpGen/Expression.h" - +#include "AmpGen/CompiledExpression.h" +using namespace AmpGen; BOOST_AUTO_TEST_CASE ( sum_to_string ) { AmpGen::Parameter A("A"); @@ -42,3 +43,15 @@ BOOST_AUTO_TEST_CASE( test_composite, * utf::tolerance(1e-6) ) double value = std::real( ( A*B/( AmpGen::fcn::cos(B) * AmpGen::fcn::sqrt(A) ))() ); BOOST_TEST( value == (4*5/(cos(5)*sqrt(4))), boost::test_tools::tolerance(1e-6)) ; } + +BOOST_AUTO_TEST_CASE( lambda_expression ) +{ + double x = 5; + LambdaExpression test( [&x](){ return x; } ); + auto f = test + 7; + BOOST_CHECK( std::real(f()) == 12 ); + auto expr = make_expression( f, "test" ); + x = 12; + expr.prepare(); // update cache state + BOOST_CHECK( expr( static_cast(nullptr)) == 19 ); +} From 1e296a410ed9a1f2e962d350078ae7d22d2a289a Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 25 Sep 2020 13:00:44 +0200 Subject: [PATCH 231/250] Fix plotting in SimFit --- examples/SimFit.cpp | 35 +++++++++++++++++------------------ src/EventListSIMD.cpp | 18 +++--------------- src/Projection.cpp | 18 +++++++++++++++++- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/examples/SimFit.cpp b/examples/SimFit.cpp index 2671093485c..9db28776b60 100644 --- a/examples/SimFit.cpp +++ b/examples/SimFit.cpp @@ -13,7 +13,14 @@ #include "AmpGen/Generator.h" #include "AmpGen/PolarisedSum.h" #ifdef _OPENMP -#include + #include +#endif +#if ENABLE_AVX + #include "AmpGen/EventListSIMD.h" + using EventList_type = AmpGen::EventListSIMD; +#else + #include "AmpGen/EventList.h" + using EventList_type = AmpGen::EventList; #endif #include "TRandom3.h" @@ -38,8 +45,8 @@ int main(int argc , char* argv[] ){ const std::string plotFile = NamedParameter("Plots" , "plots.root", "Name of the output plot file"); - std::vector data; - std::vector mcs; + std::vector data; + std::vector mcs; #ifdef _OPENMP size_t hwThreads = std::thread::hardware_concurrency(); @@ -62,7 +69,7 @@ int main(int argc , char* argv[] ){ } std::vector fcs(data.size()); - std::vector> pdfs; + std::vector> pdfs; pdfs.reserve(data.size()); @@ -71,7 +78,7 @@ int main(int argc , char* argv[] ){ mps.loadFromStream(); for(size_t i = 0; i < data.size(); ++i){ fcs[i] = PolarisedSum(eventType, mps); - pdfs.emplace_back( make_pdf(fcs[i]) ); + pdfs.emplace_back( make_pdf(fcs[i]) ); pdfs[i].setEvents(data[i]); auto& mc = mcs[i]; for_each( pdfs[i].pdfs(), [&mc](auto& pdf){pdf.setMC(mc);}); @@ -84,19 +91,11 @@ int main(int argc , char* argv[] ){ for( size_t i = 0 ; i < data.size(); ++i ) { INFO("Making figures for sample: " << i << " ..."); - auto dataPlots = data[i].makeDefaultProjections( PlotOptions::Prefix("Data_"+std::to_string(i))); - for( auto& p : dataPlots ) p->Write(); - size_t counter = 0; - for_each(pdfs[i].pdfs(), [&]( auto& f ){ - auto mc_plots = mcs[i].makeDefaultProjections(WeightFunction(f), - PlotOptions::Prefix("Model_sample_"+std::to_string(i)+"_cat"+std::to_string(counter))); - for( auto& plot : mc_plots ) - { - plot->Scale( ( data[i].integral() * f.getWeight() ) / plot->Integral() ); - plot->Write(); - } - counter++; - } ); + for( auto proj : eventType.defaultProjections() ) + { + proj(data[i], PlotOptions::Prefix("Data"+std::to_string(i)), PlotOptions::AutoWrite() ); + proj(mcs[i] , pdfs[i].componentEvaluator(&mcs[i]), PlotOptions::Prefix("pdf"+std::to_string(i)), PlotOptions::Norm(data.size()), PlotOptions::AutoWrite() ); + } } output_plots->Close(); } diff --git a/src/EventListSIMD.cpp b/src/EventListSIMD.cpp index 8a1178a2ad6..cd6b6873e6b 100644 --- a/src/EventListSIMD.cpp +++ b/src/EventListSIMD.cpp @@ -178,26 +178,14 @@ TTree* EventListSIMD::tree( const std::string& name, const std::vector EventListSIMD::makeProjections( const std::vector& projections, const ArgumentPack& args ) { std::vector plots; - for ( const auto& proj : projections ) plots.push_back( makeProjection(proj, args) ); + for ( const auto& proj : projections ) plots.push_back( proj(*this,args) ); return plots; } TH1D* EventListSIMD::makeProjection( const Projection& projection, const ArgumentPack& args ) const { - auto selection = args.getArg().val; - auto weightFunction = args.getArg().val; - std::string prefix = args.getArg(std::string("")); - auto plot = projection.plot(prefix); - plot->SetLineColor(args.getArg(kBlack).val); - plot->SetMarkerSize(0); - for( const auto evt : *this ) - { - if( selection != nullptr && !selection(evt) ) continue; - auto pos = projection(evt); - plot->Fill( pos, evt.weight() * ( weightFunction == nullptr ? 1 : weightFunction(evt) / evt.genPdf() ) ); - } - if( selection != nullptr ) INFO("Filter efficiency = " << plot->GetEntries() << " / " << size() ); - return plot; + return projection(*this, args); + } TH2D* EventListSIMD::makeProjection( const Projection2D& projection, const ArgumentPack& args ) const { diff --git a/src/Projection.cpp b/src/Projection.cpp index 0baec9f479c..5856c991717 100644 --- a/src/Projection.cpp +++ b/src/Projection.cpp @@ -80,6 +80,7 @@ template <> TH1D* Projection::projInternal( const EventList& events, const Argum { auto selection = args.getArg().val; auto weightFunction = args.getArg().val; + bool autowrite = args.get() != nullptr; std::string prefix = args.getArg(std::string("")); auto axis = plot(prefix); axis->SetLineColor(args.getArg(kBlack).val); @@ -91,6 +92,7 @@ template <> TH1D* Projection::projInternal( const EventList& events, const Argum axis->Fill( pos, evt.weight() * ( weightFunction == nullptr ? 1 : weightFunction(evt) / evt.genPdf() ) ); } if( selection != nullptr ) INFO("Filter efficiency = " << axis->GetEntries() << " / " << events.size() ); + if( autowrite ) axis->Write(); return axis; } @@ -127,7 +129,21 @@ template <> std::tuple, THStack*> Projection::projInternal(co #if ENABLE_AVX template <> TH1D* Projection::projInternal( const EventListSIMD& events, const ArgumentPack& args) const { - return events.makeProjection(*this, args); + auto selection = args.getArg().val; + auto weightFunction = args.getArg().val; + bool autowrite = args.get() != nullptr; + std::string prefix = args.getArg(std::string("")); + auto plt = plot(prefix); + plt->SetLineColor(args.getArg(kBlack).val); + plt->SetMarkerSize(0); + for( const auto evt : events ) + { + if( selection != nullptr && !selection(evt) ) continue; + auto pos = operator()(evt); + plt->Fill( pos, evt.weight() * ( weightFunction == nullptr ? 1 : weightFunction(evt) / evt.genPdf() ) ); + } + if( autowrite ) plt->Write(); + return plt; } template <> std::tuple, THStack*> Projection::projInternal(const EventListSIMD& events, const Projection::keyedFunctors& weightFunction, const ArgumentPack& args) const From 7d10d6dd6b31ee8f35a143dc559cafecacc1259c Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Mon, 28 Sep 2020 18:18:29 +0200 Subject: [PATCH 232/250] add flag to include conjugate amplitude --- apps/Generator.cpp | 9 ++++----- src/PolarisedSum.cpp | 4 +++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/Generator.cpp b/apps/Generator.cpp index 3b79639481b..72652742fc0 100644 --- a/apps/Generator.cpp +++ b/apps/Generator.cpp @@ -182,11 +182,10 @@ int main( int argc, char** argv ) NamedParameter( "GenerateTimeDependent", false , "Flag to include possible time dependence of the amplitude") ); bool conj = NamedParameter("Conj",false, "Flag to generate the CP conjugate amplitude under the assumption of CP conservation"); - if ( conj == true ) { - eventType = eventType.conj(); - INFO( eventType ); - AddCPConjugate(MPS); - } + bool add_cp_conjugate = NamedParameter("AddConj",false, "Flag to add all of the CP conjugate amplitudes, under the assumption of CP conservation"); + if ( conj ) eventType = eventType.conj(); + if( conj || add_cp_conjugate ) AddCPConjugate(MPS); + if( OptionsParser::printHelp() ) return 0; INFO("Writing output: " << outfile ); diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 75f6c2a42a0..3c30970b31c 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -205,7 +205,9 @@ void PolarisedSum::prepare() if( m_integrator.isReady() ) updateNorms(); std::for_each( m_matrixElements.begin(), m_matrixElements.end(), resetFlags ); if constexpr( detail::debug_type::value ) - if( m_nCalls % 10000 == 0 ) debug_norm(); + { + if( m_nCalls % 10000 == 0 ) debug_norm(); + } m_pdfCache.update(m_cache, m_probExpression); DEBUG( "m_pdfCache[0] = " << utils::at(m_pdfCache[0],0) << " w/o caching = " << getValNoCache(m_events->at(0)) << " w = " << m_weight << " N = " << m_norm ); m_nCalls++; From 4d39f636d64cdb3bc7885eeb9b6e7b25664fd5f9 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Tue, 6 Oct 2020 11:05:48 +0200 Subject: [PATCH 233/250] Add some logical operators + improved safety for splines using vector instructions --- AmpGen/CompiledExpression.h | 5 ++++ AmpGen/CompiledExpressionBase.h | 1 + AmpGen/Expression.h | 18 ++++++++++++++- AmpGen/gsl_wrapper.h | 41 +++++++++++++++++++++++++++++++++ AmpGen/simd/avx2d_types.h | 2 ++ AmpGen/simd/avx2f_types.h | 2 ++ src/Array.cpp | 2 +- src/BinaryExpression.cpp | 9 ++++++++ src/CompiledExpressionBase.cpp | 10 +++++--- src/Expression.cpp | 7 +++++- src/Spline.cpp | 2 -- 11 files changed, 91 insertions(+), 8 deletions(-) create mode 100644 AmpGen/gsl_wrapper.h diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index 1c08c59bd78..2c7f86a7961 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -218,6 +218,10 @@ namespace AmpGen { return link( dlopen( handle.c_str(), RTLD_NOW ) ); }; + std::string arg_type(const unsigned& i ) const override + { + return typelist()[i]; + } }; template @@ -249,6 +253,7 @@ namespace AmpGen rt.prepare(); return rt; } + } // namespace AmpGen diff --git a/AmpGen/CompiledExpressionBase.h b/AmpGen/CompiledExpressionBase.h index ab81672d567..8e2820f82c8 100644 --- a/AmpGen/CompiledExpressionBase.h +++ b/AmpGen/CompiledExpressionBase.h @@ -61,6 +61,7 @@ namespace AmpGen virtual bool use_rto() const = 0; Expression expression() const { return m_obj; } void enableBatch() { m_enableBatch = true ; } + virtual std::string arg_type( const unsigned& counter) const =0; protected: Expression m_obj; std::string m_name; diff --git a/AmpGen/Expression.h b/AmpGen/Expression.h index ce83ed82765..f48312d89f2 100644 --- a/AmpGen/Expression.h +++ b/AmpGen/Expression.h @@ -212,12 +212,13 @@ namespace AmpGen class LambdaExpression : public IExpression { public: template - LambdaExpression( const function_type& function) : m_function(function) {} + LambdaExpression( const function_type& function) : m_function(function), m_name(type_string()) {} std::string to_string(const ASTResolver* resolver = nullptr) const override; void resolve( ASTResolver& resolver) const override; operator Expression() const; complex_t operator()() const override; std::function m_function; + std::string m_name; }; /** @ingroup ExpressionEngine class Ternary @@ -309,10 +310,22 @@ namespace AmpGen /// @ingroup ExpressionEngine class GreaterThan /// @brief Binary expression that returns \f$l > r\f$ DECLARE_BINARY_OPERATOR( GreaterThan ); + + /// @ingroup ExpressionEngine class LessThanEqualTo + /// @brief Binary expression that returns \f$l < r\f$ + DECLARE_BINARY_OPERATOR( LessThanEqualTo ); + /// @ingroup ExpressionEngine class GreaterThanEqualTo + /// @brief Binary expression that returns \f$l > r\f$ + DECLARE_BINARY_OPERATOR( GreaterThanEqualTo ); + /// @ingroup ExpressionEngine class And /// @brief Binary expression that returns \f$l \wedge r\f$ DECLARE_BINARY_OPERATOR( And ); + + /// @ingroup ExpressionEngine class Or + /// @brief Binary expression that returns \f$l \wedge r\f$ + DECLARE_BINARY_OPERATOR( Or ); DECLARE_BINARY_OPERATOR( Equal ); DECLARE_BINARY_OPERATOR( ATan2 ); @@ -393,6 +406,8 @@ namespace AmpGen Expression operator<( const Expression& A, const Expression& B ); Expression operator>( const Expression& A, const Expression& B ); + Expression operator<=( const Expression& A, const Expression& B ); + Expression operator>=( const Expression& A, const Expression& B ); Expression operator+( const Expression& A, const Expression& B ); Expression operator-( const Expression& A, const Expression& B ); @@ -418,6 +433,7 @@ namespace AmpGen Expression operator/( const T& A, const Expression& B ){ return Constant(A) / B; } Expression operator&&( const Expression& A, const Expression& B ); + Expression operator||( const Expression& A, const Expression& B ); Expression operator==( const Expression& A, const Expression& B ); Expression operator==( const Expression& A, const double& B ); Expression operator==( const double& A, const Expression& B ); diff --git a/AmpGen/gsl_wrapper.h b/AmpGen/gsl_wrapper.h new file mode 100644 index 00000000000..04bcc9306ee --- /dev/null +++ b/AmpGen/gsl_wrapper.h @@ -0,0 +1,41 @@ + +#include + +namespace AmpGen { + template double integrate_1d( const function_type& fcn, const double& min, const double& max, gsl_integration_workspace* ws = nullptr) + { + gsl_integration_workspace* w = (ws == nullptr) ? gsl_integration_workspace_alloc (1000) : ws; + double result = 0; + double error = 0; + gsl_function F; + F.function = [](double x, void* p) -> double { return (*static_cast(p))(x); }; + F.params = const_cast(&fcn); + gsl_integration_qags (&F, min, max, 0, 1e-5, 1000, w, &result, &error); + if( ws == nullptr ) gsl_integration_workspace_free (w); + return result; + } + template double integrate_2d( const function_type& fcn, const double& x1, const double& x2, const double& y1, const double& y2) + { + gsl_integration_workspace* w1 = gsl_integration_workspace_alloc (1000); + auto outer = [fcn, &x1, &x2, &w1](const double& y) + { + auto inner = [fcn, &y](const double& x){ return fcn(x,y); }; + return integrate_1d(inner, x1,x2, w1); + }; + auto r = integrate_1d( outer, y1, y2); + gsl_integration_workspace_free (w1); + return r; + } + template double integrate_1d_cauchy( const function_type& fcn, const double& x0, const double& min, const double& max, gsl_integration_workspace* ws = nullptr) + { + gsl_integration_workspace* w = (ws == nullptr) ? gsl_integration_workspace_alloc (1000) : ws; + double result = 0; + double error = 0; + gsl_function F; + F.function = [](double x, void* p) -> double { return (*static_cast(p))(x); }; + F.params = const_cast(&fcn); + gsl_integration_qawc(&F, min, max, x0, 0, 1e-5, 1000, w, &result, &error); + if( ws == nullptr ) gsl_integration_workspace_free (w); + return result; + } +} diff --git a/AmpGen/simd/avx2d_types.h b/AmpGen/simd/avx2d_types.h index c232663eaee..f1b0cbea97e 100644 --- a/AmpGen/simd/avx2d_types.h +++ b/AmpGen/simd/avx2d_types.h @@ -60,6 +60,8 @@ namespace AmpGen { inline real_v operator!( const real_v& x ) { return x ^ _mm256_castsi256_pd( _mm256_set1_epi32( -1 ) ); } inline real_v operator<( const real_v& lhs, const real_v& rhs ) { return _mm256_cmp_pd( lhs, rhs, _CMP_LT_OS ); } inline real_v operator>( const real_v& lhs, const real_v& rhs ) { return _mm256_cmp_pd( lhs, rhs, _CMP_GT_OS ); } + inline real_v operator<=( const real_v& lhs, const real_v& rhs ) { return _mm256_cmp_pd( lhs, rhs, _CMP_LE_OS ); } + inline real_v operator>=( const real_v& lhs, const real_v& rhs ) { return _mm256_cmp_pd( lhs, rhs, _CMP_GE_OS ); } inline real_v operator==( const real_v& lhs, const real_v& rhs ){ return _mm256_cmp_pd( lhs, rhs, _CMP_EQ_OS ); } inline real_v sqrt( const real_v& v ) { return _mm256_sqrt_pd(v); } inline real_v abs ( const real_v& v ) { return _mm256_andnot_pd(_mm256_set1_pd(-0.), v); } diff --git a/AmpGen/simd/avx2f_types.h b/AmpGen/simd/avx2f_types.h index d5fc784b3ba..66a91df9431 100644 --- a/AmpGen/simd/avx2f_types.h +++ b/AmpGen/simd/avx2f_types.h @@ -62,6 +62,8 @@ namespace AmpGen { inline real_v operator!( const real_v& x ) { return x ^ _mm256_castsi256_ps( _mm256_set1_epi32( -1 ) ); } inline real_v operator<( const real_v& lhs, const real_v& rhs ) { return _mm256_cmp_ps( lhs, rhs, _CMP_LT_OS ); } inline real_v operator>( const real_v& lhs, const real_v& rhs ) { return _mm256_cmp_ps( lhs, rhs, _CMP_GT_OS ); } + inline real_v operator<( const real_v& lhs, const real_v& rhs ) { return _mm256_cmp_ps( lhs, rhs, _CMP_LE_OS ); } + inline real_v operator>( const real_v& lhs, const real_v& rhs ) { return _mm256_cmp_ps( lhs, rhs, _CMP_GE_OS ); } inline real_v operator==( const real_v& lhs, const real_v& rhs ){ return _mm256_cmp_ps( lhs, rhs, _CMP_EQ_OS ); } inline real_v sqrt( const real_v& v ) { return _mm256_sqrt_ps(v); } libmvec_alias(sin) diff --git a/src/Array.cpp b/src/Array.cpp index fe66b64b347..faaedacbf52 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -19,7 +19,7 @@ Array::Array( const Expression& top, std::string Array::to_string(const ASTResolver* resolver) const { auto head = m_top.to_string(resolver); - auto offset = m_address.to_string(resolver); + auto offset = Ternary( m_address >= 0 && m_address < m_size, m_address, 0.).to_string(resolver); if( resolver != nullptr && resolver->enableAVX() ) return " gather( &(" + head + "), " + offset + ")"; if( head.find("[") == std::string::npos ) return head + "[int("+offset+")]"; else return " * ( & (" + head + ") + int("+offset+") )"; diff --git a/src/BinaryExpression.cpp b/src/BinaryExpression.cpp index fdd516580d4..9416412a7ab 100644 --- a/src/BinaryExpression.cpp +++ b/src/BinaryExpression.cpp @@ -18,6 +18,9 @@ DEFINE_BINARY_OPERATOR( Equal ) DEFINE_BINARY_OPERATOR( Pow ) DEFINE_BINARY_OPERATOR( Fmod ) DEFINE_BINARY_OPERATOR( ATan2 ) +DEFINE_BINARY_OPERATOR( GreaterThanEqualTo ) +DEFINE_BINARY_OPERATOR( LessThanEqualTo ) +DEFINE_BINARY_OPERATOR( Or ) template < class condition > std::string bracketed( const Expression& expression, condition&& use_brackets, const ASTResolver* resolver=nullptr ){ @@ -31,9 +34,12 @@ complex_t Divide::operator()() const { return lval() / rval(); } complex_t And::operator()() const { return complex_t(std::real(lval()) && std::real(rval()),0); } complex_t GreaterThan::operator()() const { return complex_t(std::real(lval()) > std::real(rval()) ,0); } complex_t LessThan::operator()() const { return complex_t(std::real(lval()) < std::real(rval()) ,0); } +complex_t GreaterThanEqualTo::operator()() const { return complex_t(std::real(lval()) >= std::real(rval()) ,0); } +complex_t LessThanEqualTo::operator()() const { return complex_t(std::real(lval()) <= std::real(rval()) ,0); } complex_t Pow::operator()() const { return pow( lval(), rval() ); } complex_t Fmod::operator()() const { return 0; } complex_t Equal::operator()() const { return lval() == rval() ; } +complex_t Or::operator()() const { return std::real(lval()) || std::real(rval()) ; } complex_t ATan2::operator()() const { return atan2( std::real(lval() ), std::real(rval() ) ); } std::string Sum::to_string(const ASTResolver* resolver) const @@ -63,6 +69,9 @@ std::string Divide::to_string(const ASTResolver* resolver) const { std::string LessThan::to_string(const ASTResolver* resolver) const { return "(" + lval.to_string(resolver) + "<" + rval.to_string(resolver) +")"; } std::string GreaterThan::to_string(const ASTResolver* resolver) const { return "(" + lval.to_string(resolver) + ">" + rval.to_string(resolver) +")"; } std::string And::to_string(const ASTResolver* resolver) const { return "(" + lval.to_string(resolver) + "&&" + rval.to_string(resolver) +")"; } +std::string LessThanEqualTo::to_string(const ASTResolver* resolver) const { return "(" + lval.to_string(resolver) + "<=" + rval.to_string(resolver) +")"; } +std::string GreaterThanEqualTo::to_string(const ASTResolver* resolver) const { return "(" + lval.to_string(resolver) + ">=" + rval.to_string(resolver) +")"; } +std::string Or::to_string(const ASTResolver* resolver) const { return "(" + lval.to_string(resolver) + "||" + rval.to_string(resolver) +")"; } std::string Pow::to_string(const ASTResolver* resolver) const { return "pow(" + lval.to_string(resolver) + ", " + rval.to_string(resolver) +")"; } std::string Fmod::to_string(const ASTResolver* resolver) const { return "fmod(" + lval.to_string(resolver) + "," + rval.to_string(resolver) +")"; } std::string ATan2::to_string( const ASTResolver* resolver) const { return "atan2("+ lval.to_string(resolver) + "," + rval.to_string(resolver) +")"; } diff --git a/src/CompiledExpressionBase.cpp b/src/CompiledExpressionBase.cpp index 864f13f3389..ac2bf0c7524 100644 --- a/src/CompiledExpressionBase.cpp +++ b/src/CompiledExpressionBase.cpp @@ -94,16 +94,20 @@ void CompiledExpressionBase::to_stream( std::ostream& stream ) const size_t sizeOfStream = 0; if( use_rto() ) { + stream << "extern \"C\" " << returnTypename() << " " << progName() << "(" << fcnSignature() << "){\n"; - addDependentExpressions( stream , sizeOfStream ); + addDependentExpressions( stream , sizeOfStream );\ + std::string return_type = arg_type(0); + return_type = return_type.substr(0,return_type.size()-1); if( is(m_obj) == false ){ - stream << "*r = " << m_obj.to_string(m_resolver.get()) << ";\n"; + stream << "*r = " << return_type << "(" << m_obj.to_string(m_resolver.get()) << ");\n"; stream << "}\n"; } else { auto as_tensor = cast(m_obj).tensor(); + for(unsigned j=0; j != as_tensor.size(); ++j ) - stream << "r[s * "<< j<<"] = " << as_tensor[j].to_string(m_resolver.get()) << ";\n"; + stream << "r[s * "<< j<<"] = " << return_type << "(" << as_tensor[j].to_string(m_resolver.get()) << ");\n"; stream << "}\n"; } } diff --git a/src/Expression.cpp b/src/Expression.cpp index db09f2283b3..930bfb13822 100644 --- a/src/Expression.cpp +++ b/src/Expression.cpp @@ -16,6 +16,7 @@ #include "AmpGen/MsgService.h" #include "AmpGen/Types.h" #include "AmpGen/simd/utils.h" +#include "AmpGen/CompiledExpressionBase.h" using namespace AmpGen; using namespace AmpGen::fcn; using namespace std::complex_literals; @@ -166,6 +167,10 @@ Expression AmpGen::operator==( const Expression& A, const Expression& B ){ retur Expression AmpGen::operator==( const double& A, const Expression& B ){ return Constant(A) == B ; } Expression AmpGen::operator==( const Expression& A, const double& B ){ return A == Constant(B) ; } +Expression AmpGen::operator||( const Expression& A, const Expression& B){ return Expression( Or(A,B)) ; } +Expression AmpGen::operator<=( const Expression& A, const Expression& B ){ return LessThanEqualTo(A,B) ; } +Expression AmpGen::operator>=( const Expression& A, const Expression& B ){ return GreaterThanEqualTo(A,B) ; } + Parameter::Parameter( const std::string& name, const double& defaultValue, const bool& resolved) : m_name( name ) , m_defaultValue( defaultValue ) @@ -343,7 +348,7 @@ complex_t ComplexParameter::operator()() const std::string LambdaExpression::to_string(const ASTResolver* resolver) const { - if( resolver == nullptr ){ WARNING("Not clear what is is you're trying to do here"); return "";} return resolver->resolvedParameter(this); + return resolver == nullptr ?programatic_name(m_name) : resolver->resolvedParameter(this); } complex_t LambdaExpression::operator()() const diff --git a/src/Spline.cpp b/src/Spline.cpp index ed4fcf38530..1a1ee7b3b61 100644 --- a/src/Spline.cpp +++ b/src/Spline.cpp @@ -76,8 +76,6 @@ Expression Spline::eval(DebugSymbols* db) const ADD_DEBUG(bin, db ); ADD_DEBUG(returnValue, db ); ADD_DEBUG( m_points[bin], db ); - for( int i = 0 ; i != m_points.size(); ++i ) - ADD_DEBUG( m_points[Constant(i) + 0.1], db ); return make_cse(returnValue); } From e77543c16befdceefeb584025bee01c2068f7aa7 Mon Sep 17 00:00:00 2001 From: tevans Date: Fri, 16 Oct 2020 16:52:41 +0200 Subject: [PATCH 234/250] Modified simultaneous fit to be able to describe multiple types of events not just data taking categories --- examples/SimFit.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/examples/SimFit.cpp b/examples/SimFit.cpp index 9db28776b60..95345cd2797 100644 --- a/examples/SimFit.cpp +++ b/examples/SimFit.cpp @@ -12,6 +12,7 @@ #include "AmpGen/Kinematics.h" #include "AmpGen/Generator.h" #include "AmpGen/PolarisedSum.h" +#include "AmpGen/AddCPConjugate.h" #ifdef _OPENMP #include #endif @@ -32,9 +33,6 @@ using namespace AmpGen; int main(int argc , char* argv[] ){ OptionsParser::setArgs( argc, argv ); - const auto pEventType = NamedParameter("EventType", std::vector(), - "EventType to fit, in the format: \033[3m parent daughter1 daughter2 ... \033[0m" ).getVector(); - const auto datasets = NamedParameter("Datasets","", "List of data/simulated samples to fit, in the format \ \033[3m data[0] sim[0] data[1] sim[1] ... \033[0m. \nIf a simulated sample is specified FLAT, uniformly generated phase-space events are used for integrals ").getVector(); @@ -44,6 +42,8 @@ int main(int argc , char* argv[] ){ const std::string plotFile = NamedParameter("Plots" , "plots.root", "Name of the output plot file"); + + const bool add_conj = NamedParameter("AddConj", false ); std::vector data; std::vector mcs; @@ -58,14 +58,10 @@ int main(int argc , char* argv[] ){ INFO("Output : " << logFile << " plots = " << plotFile ); - if( pEventType.size() == 0 ) FATAL("Must specify event format as EventType \033[3m parent daughter1 daughter2 ... \033[0m in options"); - - const EventType eventType = EventType( pEventType ); - for(size_t i=0;i < datasets.size() ; i+=2 ){ - data.emplace_back( datasets[i], eventType ); - if( datasets[i+1] == "FLAT" ) mcs.emplace_back(Generator<>(eventType).generate(1e6)); - else mcs.emplace_back( datasets[i+1], eventType, GetGenPdf(true) ); + data.emplace_back( datasets[i] ); + if( datasets[i+1] == "FLAT" ) mcs.emplace_back(Generator<>(data.rbegin()->eventType() ).generate(1e6)); + else mcs.emplace_back( datasets[i+1], data.rbegin()->eventType(), GetGenPdf(true) ); } std::vector fcs(data.size()); @@ -76,8 +72,9 @@ int main(int argc , char* argv[] ){ SimFit totalLL; MinuitParameterSet mps; mps.loadFromStream(); + if( add_conj ) AddCPConjugate(mps); for(size_t i = 0; i < data.size(); ++i){ - fcs[i] = PolarisedSum(eventType, mps); + fcs[i] = PolarisedSum(data[i].eventType(), mps); pdfs.emplace_back( make_pdf(fcs[i]) ); pdfs[i].setEvents(data[i]); auto& mc = mcs[i]; @@ -91,7 +88,7 @@ int main(int argc , char* argv[] ){ for( size_t i = 0 ; i < data.size(); ++i ) { INFO("Making figures for sample: " << i << " ..."); - for( auto proj : eventType.defaultProjections() ) + for( auto proj : data[i].eventType().defaultProjections() ) { proj(data[i], PlotOptions::Prefix("Data"+std::to_string(i)), PlotOptions::AutoWrite() ); proj(mcs[i] , pdfs[i].componentEvaluator(&mcs[i]), PlotOptions::Prefix("pdf"+std::to_string(i)), PlotOptions::Norm(data.size()), PlotOptions::AutoWrite() ); From 992f2e2a18f15917b3ce7b6d10a15877d9dcaddc Mon Sep 17 00:00:00 2001 From: Maurizio Martinelli Date: Mon, 26 Oct 2020 15:31:58 +0100 Subject: [PATCH 235/250] fixed a compilation errore in systems where OMP is not available --- AmpGen/simd/avx2d_types.h | 80 ++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/AmpGen/simd/avx2d_types.h b/AmpGen/simd/avx2d_types.h index f1b0cbea97e..e3e0349d7fb 100644 --- a/AmpGen/simd/avx2d_types.h +++ b/AmpGen/simd/avx2d_types.h @@ -5,14 +5,16 @@ #include #include #include +#ifdef _OPENMP #include +#endif #include #if USE_MVEC extern "C" void _ZGVdN4vvv_sincos(__m256d x, __m256i ptrs, __m256i ptrc); #endif -#if USE_MVEC +#if USE_MVEC #define libmvec_alias( function_name) \ extern "C" __m256d _ZGVcN4v_##function_name(__m256d x); \ inline real_v function_name( const real_v& v ){ return _ZGVcN4v_##function_name (v) ; } @@ -28,19 +30,19 @@ namespace AmpGen { __m256d data; static constexpr unsigned size = 4; typedef double scalar_type; - real_v() = default; + real_v() = default; real_v(__m256d data ) : data(data) {} real_v(const double& f ) : data( _mm256_set1_pd( f )) {} real_v(const double& x0, const double& x1, const double& x2, const double& x3 ) { - data = _mm256_set_pd(x3,x2,x1,x0); + data = _mm256_set_pd(x3,x2,x1,x0); } real_v(const double* f ) : data( _mm256_loadu_pd( f ) ) {} real_v(const std::array f ) : data( _mm256_loadu_pd( f.data() ) ) {} void store( double* ptr ) const { _mm256_storeu_pd( ptr, data ); } std::array to_array() const { std::array b; store( &b[0] ); return b; } - double at(const unsigned i) const { return to_array()[i] ; } - operator __m256d() const { return data ; } + double at(const unsigned i) const { return to_array()[i] ; } + operator __m256d() const { return data ; } }; inline real_v operator+( const real_v& lhs, const real_v& rhs ) { return _mm256_add_pd(lhs, rhs); } @@ -63,7 +65,7 @@ namespace AmpGen { inline real_v operator<=( const real_v& lhs, const real_v& rhs ) { return _mm256_cmp_pd( lhs, rhs, _CMP_LE_OS ); } inline real_v operator>=( const real_v& lhs, const real_v& rhs ) { return _mm256_cmp_pd( lhs, rhs, _CMP_GE_OS ); } inline real_v operator==( const real_v& lhs, const real_v& rhs ){ return _mm256_cmp_pd( lhs, rhs, _CMP_EQ_OS ); } - inline real_v sqrt( const real_v& v ) { return _mm256_sqrt_pd(v); } + inline real_v sqrt( const real_v& v ) { return _mm256_sqrt_pd(v); } inline real_v abs ( const real_v& v ) { return _mm256_andnot_pd(_mm256_set1_pd(-0.), v); } libmvec_alias( sin ) libmvec_alias( cos ) @@ -73,9 +75,9 @@ namespace AmpGen { inline void sincos( const real_v& v, real_v& s, real_v& c ) { #if USE_MVEC - __m256i sp = _mm256_add_epi64(_mm256_set1_epi64x((uint64_t)&s),_mm256_set_epi64x(24,16,8,0)); - __m256i cp = _mm256_add_epi64(_mm256_set1_epi64x((uint64_t)&c),_mm256_set_epi64x(24,16,8,0)); - _ZGVdN4vvv_sincos(v,sp,cp); + __m256i sp = _mm256_add_epi64(_mm256_set1_epi64x((uint64_t)&s),_mm256_set_epi64x(24,16,8,0)); + __m256i cp = _mm256_add_epi64(_mm256_set1_epi64x((uint64_t)&c),_mm256_set_epi64x(24,16,8,0)); + _ZGVdN4vvv_sincos(v,sp,cp); #else s = sin(v); c = cos(v); @@ -85,37 +87,37 @@ namespace AmpGen { { std::pair rt; sincos( v, rt.first, rt.second ); - return rt; + return rt; } inline real_v tan( const real_v& v ) { auto [s,c] = sincos( v ); - return s / c ; + return s / c ; } inline real_v select(const real_v& mask, const real_v& a, const real_v& b ) { return _mm256_blendv_pd( b, a, mask ); } - inline real_v select(const bool& mask , const real_v& a, const real_v& b ) { return mask ? a : b; } + inline real_v select(const bool& mask , const real_v& a, const real_v& b ) { return mask ? a : b; } inline real_v sign ( const real_v& v){ return select( v > 0., +1., -1. ); } - inline real_v atan2( const real_v& y, const real_v& x ){ + inline real_v atan2( const real_v& y, const real_v& x ){ std::array bx{x.to_array()}, by{y.to_array()}; - return real_v ( - std::atan2( by[0], bx[0]) - , std::atan2( by[1], bx[1]) - , std::atan2( by[2], bx[2]) - , std::atan2( by[3], bx[3]) ); + return real_v ( + std::atan2( by[0], bx[0]) + , std::atan2( by[1], bx[1]) + , std::atan2( by[2], bx[2]) + , std::atan2( by[3], bx[3]) ); } inline __m256i udouble_to_uint( const real_v& x ) { auto xr = _mm256_round_pd(x, _MM_FROUND_TO_NEG_INF); // based on: https://stackoverflow.com/questions/41144668/how-to-efficiently-perform-double-int64-conversions-with-sse-avx - return _mm256_sub_epi64(_mm256_castpd_si256(_mm256_add_pd(xr, _mm256_set1_pd(0x0018000000000000))), + return _mm256_sub_epi64(_mm256_castpd_si256(_mm256_add_pd(xr, _mm256_set1_pd(0x0018000000000000))), _mm256_castpd_si256(_mm256_set1_pd(0x0018000000000000))); } - inline real_v gather( const double* base_addr, const real_v& offsets) + inline real_v gather( const double* base_addr, const real_v& offsets) { return _mm256_i64gather_pd(base_addr, udouble_to_uint(offsets),sizeof(double)); - } - + } + inline real_v fmadd( const real_v& a, const real_v& b, const real_v& c ) { return _mm256_fmadd_pd(a, b, c); @@ -136,40 +138,40 @@ namespace AmpGen { real_v real() const { return re; } real_v imag() const { return im; } real_v norm() const { return re*re + im *im ; } - complex_v() = default; + complex_v() = default; complex_v( const real_v& re, const real_v& im) : re(re), im(im) {} complex_v( const float& re, const float& im) : re(re), im(im) {} complex_v( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} complex_v( const std::complex& f ) : re( f.real() ), im( f.imag() ) {} complex_v( const std::complex* arr ) : re ( arr[0].real(), arr[1].real(), arr[2].real(), arr[3].real() ), - im ( arr[0].imag(), arr[1].imag(), arr[2].imag(), arr[3].imag() ){} + im ( arr[0].imag(), arr[1].imag(), arr[2].imag(), arr[3].imag() ){} explicit complex_v( const real_v& arg ) : re(arg) {}; explicit complex_v( const double& arg ) : re(arg) {}; - const std::complex at(const unsigned i) const { return std::complex(re.to_array()[i], im.to_array()[i]) ; } - void store( double* sre, double* sim ){ re.store(sre); im.store(sim); } - void store( scalar_type* r ) const { + const std::complex at(const unsigned i) const { return std::complex(re.to_array()[i], im.to_array()[i]) ; } + void store( double* sre, double* sim ){ re.store(sre); im.store(sim); } + void store( scalar_type* r ) const { auto re_arr = re.to_array(); auto im_arr = im.to_array(); - for( unsigned i = 0 ; i != re_arr.size(); ++i ) r[i] = scalar_type( re_arr[i], im_arr[i] ); + for( unsigned i = 0 ; i != re_arr.size(); ++i ) r[i] = scalar_type( re_arr[i], im_arr[i] ); } - auto to_array() const + auto to_array() const { std::array rt; store( rt.data() ); return rt; } }; - - inline std::ostream& operator<<( std::ostream& os, const real_v& obj ) { + + inline std::ostream& operator<<( std::ostream& os, const real_v& obj ) { auto buffer = obj.to_array(); for( unsigned i = 0 ; i != 4; ++i ) os << buffer[i] << " "; - return os; + return os; } inline real_v real(const complex_v& arg ){ return arg.re ; } inline real_v imag(const complex_v& arg ){ return arg.im ; } inline complex_v conj(const complex_v& arg ){ return complex_v(arg.re, -arg.im) ; } - inline real_v conj(const real_v& arg ){ return arg ; } + inline real_v conj(const real_v& arg ){ return arg ; } inline complex_v operator+( const complex_v& lhs, const real_v& rhs ) { return complex_v(lhs.re + rhs, lhs.im); } inline complex_v operator-( const complex_v& lhs, const real_v& rhs ) { return complex_v(lhs.re - rhs, lhs.im); } inline complex_v operator*( const complex_v& lhs, const real_v& rhs ) { return complex_v(lhs.re*rhs, lhs.im*rhs); } @@ -189,7 +191,7 @@ namespace AmpGen { inline complex_v select(const real_v& mask, const real_v& a, const complex_v& b ) { return complex_v( select(mask, a , b.re), select(mask, 0.f, b.im) ); } inline complex_v select(const real_v& mask, const complex_v& a, const real_v& b ) { return complex_v( select(mask, a.re, b ) , select(mask, a.im, 0.f) ); } inline complex_v select(const bool& mask , const complex_v& a, const complex_v& b ) { return mask ? a : b; } - inline complex_v exp( const complex_v& v ){ + inline complex_v exp( const complex_v& v ){ auto [s,c] = sincos( v.im); return exp(v.re) * complex_v(c, s); } @@ -201,15 +203,15 @@ namespace AmpGen { inline complex_v log( const complex_v& v ) { return complex_v( 0.5 * log( v.norm() ) , atan2(v.im, v.re) ); - } + } inline std::ostream& operator<<( std::ostream& os, const complex_v& obj ) { return os << "( "<< obj.re << ") (" << obj.im << ")"; } #pragma omp declare reduction(+: real_v: \ - omp_out = omp_out + omp_in) + omp_out = omp_out + omp_in) #pragma omp declare reduction(+: complex_v: \ - omp_out = omp_out + omp_in) - - } + omp_out = omp_out + omp_in) + + } } #endif From 11bc9eca2ff7b70439e40fad2648f2b2268a8b78 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 28 Oct 2020 16:01:46 +0100 Subject: [PATCH 236/250] Changes for 2.1 to improve Gauss integration --- .ci/travis_linux.sh | 2 +- .ci/travis_osx.sh | 4 +- AmpGen/CoherentSum.h | 2 +- AmpGen/CompiledExpression.h | 4 +- AmpGen/PolarisedSum.h | 1 + CMakeLists.txt | 298 +++++++- README.md | 282 ++++--- README.tex.md | 252 +++--- Standalone.cmake | 233 ------ apps/{Generator.cpp => AmpGen.cpp} | 57 +- apps/ConvertToSourceCode.cpp | 149 ---- apps/{lib_diff.cpp => LibDiff.cpp} | 0 doc/figs/k3pi_s01.svg | 593 +++++++++++++++ doc/figs/lb2jspiL_s01.svg | 544 +++++++++++++ doc/figs/lb2jspiL_s012.svg | 555 ++++++++++++++ doc/figs/lb2pKpi_s01.svg | 594 +++++++++++++++ doc/figs/lb2pKpi_s02.svg | 713 +++++++++++++++++ doc/figs/lb2pKpi_s12.svg | 715 ++++++++++++++++++ doc/figs/s12.svg | 715 ++++++++++++++++++ doc/figs/tex/fig0.png | Bin 688 -> 0 bytes doc/figs/tex/fig0.svg | 67 ++ doc/figs/tex/fig1.png | Bin 744 -> 0 bytes doc/figs/tex/fig1.svg | 71 ++ doc/figs/tex/fig10.png | Bin 716 -> 0 bytes doc/figs/tex/fig10.svg | 37 + doc/figs/tex/fig11.png | Bin 688 -> 0 bytes doc/figs/tex/fig11.svg | 35 + doc/figs/tex/fig12.png | Bin 565 -> 0 bytes doc/figs/tex/fig12.svg | 37 + doc/figs/tex/fig13.png | Bin 450 -> 0 bytes doc/figs/tex/fig13.svg | 37 + doc/figs/tex/fig14.png | Bin 342 -> 0 bytes doc/figs/tex/fig14.svg | 99 +++ doc/figs/tex/fig15.svg | 37 + doc/figs/tex/fig16.svg | 89 +++ doc/figs/tex/fig17.svg | 37 + doc/figs/tex/fig18.svg | 118 +++ doc/figs/tex/fig19.svg | 32 + doc/figs/tex/fig2.png | Bin 404 -> 0 bytes doc/figs/tex/fig2.svg | 23 + doc/figs/tex/fig20.svg | 36 + doc/figs/tex/fig21.svg | 105 +++ doc/figs/tex/fig22.svg | 63 ++ doc/figs/tex/fig23.svg | 77 ++ doc/figs/tex/fig24.svg | 57 ++ doc/figs/tex/fig25.svg | 23 + doc/figs/tex/fig26.svg | 165 ++++ doc/figs/tex/fig27.svg | 45 ++ doc/figs/tex/fig28.svg | 57 ++ doc/figs/tex/fig29.svg | 89 +++ doc/figs/tex/fig3.png | Bin 406 -> 0 bytes doc/figs/tex/fig3.svg | 23 + doc/figs/tex/fig30.svg | 38 + doc/figs/tex/fig31.svg | 36 + doc/figs/tex/fig32.svg | 204 +++++ doc/figs/tex/fig33.svg | 61 ++ doc/figs/tex/fig34.svg | 67 ++ doc/figs/tex/fig35.svg | 67 ++ doc/figs/tex/fig36.svg | 90 +++ doc/figs/tex/fig37.svg | 67 ++ doc/figs/tex/fig38.svg | 70 ++ doc/figs/tex/fig39.svg | 105 +++ doc/figs/tex/fig4.png | Bin 708 -> 0 bytes doc/figs/tex/fig4.svg | 136 ++++ doc/figs/tex/fig40.svg | 67 ++ doc/figs/tex/fig41.svg | 87 +++ doc/figs/tex/fig42.svg | 43 ++ doc/figs/tex/fig43.svg | 24 + doc/figs/tex/fig44.svg | 43 ++ doc/figs/tex/fig45.svg | 23 + doc/figs/tex/fig5.png | Bin 688 -> 0 bytes doc/figs/tex/fig5.svg | 114 +++ doc/figs/tex/fig6.png | Bin 688 -> 0 bytes doc/figs/tex/fig6.svg | 103 +++ doc/figs/tex/fig7.png | Bin 761 -> 0 bytes doc/figs/tex/fig7.svg | 23 + doc/figs/tex/fig8.png | Bin 688 -> 0 bytes doc/figs/tex/fig8.svg | 23 + doc/figs/tex/fig9.png | Bin 675 -> 0 bytes doc/figs/tex/fig9.svg | 158 ++++ doc/release.notes | 5 +- ...arameters.cpp => FitHyperonParameters.cpp} | 0 src/ASTResolver.cpp | 2 +- src/CoherentSum.cpp | 6 +- src/PolarisedSum.cpp | 2 +- src/Vertex.cpp | 16 +- 86 files changed, 8230 insertions(+), 622 deletions(-) delete mode 100644 Standalone.cmake rename apps/{Generator.cpp => AmpGen.cpp} (82%) delete mode 100644 apps/ConvertToSourceCode.cpp rename apps/{lib_diff.cpp => LibDiff.cpp} (100%) create mode 100644 doc/figs/k3pi_s01.svg create mode 100644 doc/figs/lb2jspiL_s01.svg create mode 100644 doc/figs/lb2jspiL_s012.svg create mode 100644 doc/figs/lb2pKpi_s01.svg create mode 100644 doc/figs/lb2pKpi_s02.svg create mode 100644 doc/figs/lb2pKpi_s12.svg create mode 100644 doc/figs/s12.svg delete mode 100644 doc/figs/tex/fig0.png create mode 100644 doc/figs/tex/fig0.svg delete mode 100644 doc/figs/tex/fig1.png create mode 100644 doc/figs/tex/fig1.svg delete mode 100644 doc/figs/tex/fig10.png create mode 100644 doc/figs/tex/fig10.svg delete mode 100644 doc/figs/tex/fig11.png create mode 100644 doc/figs/tex/fig11.svg delete mode 100644 doc/figs/tex/fig12.png create mode 100644 doc/figs/tex/fig12.svg delete mode 100644 doc/figs/tex/fig13.png create mode 100644 doc/figs/tex/fig13.svg delete mode 100644 doc/figs/tex/fig14.png create mode 100644 doc/figs/tex/fig14.svg create mode 100644 doc/figs/tex/fig15.svg create mode 100644 doc/figs/tex/fig16.svg create mode 100644 doc/figs/tex/fig17.svg create mode 100644 doc/figs/tex/fig18.svg create mode 100644 doc/figs/tex/fig19.svg delete mode 100644 doc/figs/tex/fig2.png create mode 100644 doc/figs/tex/fig2.svg create mode 100644 doc/figs/tex/fig20.svg create mode 100644 doc/figs/tex/fig21.svg create mode 100644 doc/figs/tex/fig22.svg create mode 100644 doc/figs/tex/fig23.svg create mode 100644 doc/figs/tex/fig24.svg create mode 100644 doc/figs/tex/fig25.svg create mode 100644 doc/figs/tex/fig26.svg create mode 100644 doc/figs/tex/fig27.svg create mode 100644 doc/figs/tex/fig28.svg create mode 100644 doc/figs/tex/fig29.svg delete mode 100644 doc/figs/tex/fig3.png create mode 100644 doc/figs/tex/fig3.svg create mode 100644 doc/figs/tex/fig30.svg create mode 100644 doc/figs/tex/fig31.svg create mode 100644 doc/figs/tex/fig32.svg create mode 100644 doc/figs/tex/fig33.svg create mode 100644 doc/figs/tex/fig34.svg create mode 100644 doc/figs/tex/fig35.svg create mode 100644 doc/figs/tex/fig36.svg create mode 100644 doc/figs/tex/fig37.svg create mode 100644 doc/figs/tex/fig38.svg create mode 100644 doc/figs/tex/fig39.svg delete mode 100644 doc/figs/tex/fig4.png create mode 100644 doc/figs/tex/fig4.svg create mode 100644 doc/figs/tex/fig40.svg create mode 100644 doc/figs/tex/fig41.svg create mode 100644 doc/figs/tex/fig42.svg create mode 100644 doc/figs/tex/fig43.svg create mode 100644 doc/figs/tex/fig44.svg create mode 100644 doc/figs/tex/fig45.svg delete mode 100644 doc/figs/tex/fig5.png create mode 100644 doc/figs/tex/fig5.svg delete mode 100644 doc/figs/tex/fig6.png create mode 100644 doc/figs/tex/fig6.svg delete mode 100644 doc/figs/tex/fig7.png create mode 100644 doc/figs/tex/fig7.svg delete mode 100644 doc/figs/tex/fig8.png create mode 100644 doc/figs/tex/fig8.svg delete mode 100644 doc/figs/tex/fig9.png create mode 100644 doc/figs/tex/fig9.svg rename examples/{fit_hyperon_parameters.cpp => FitHyperonParameters.cpp} (100%) diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh index 16acae4bab8..93f735a9fe4 100755 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -19,5 +19,5 @@ set +evx cd .. -./build.conda/bin/Generator options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 10000 +./build.conda/bin/AmpGen.exe options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 10000 diff --git a/.ci/travis_osx.sh b/.ci/travis_osx.sh index 2c68f74053a..a670e2936a6 100644 --- a/.ci/travis_osx.sh +++ b/.ci/travis_osx.sh @@ -10,9 +10,9 @@ echo "Building under OS: $TRAVIS_OS_NAME" mkdir -p build cd build echo "CMake-ing, CXX = $CXX" -cmake .. -DCMAKE_CXX_COMPILER=clang -DUSE_SIMD="" -DUSE_OPENMP=0 +cmake .. -DCMAKE_CXX_COMPILER=clang -DUSE_SIMD=0 -DUSE_OPENMP=0 echo "Building ..." cmake --build . -- -j2 cd .. echo "Running test job ..." -./build/bin/Generator options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 10000 +./build/bin/AmpGen.exe options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 10000 diff --git a/AmpGen/CoherentSum.h b/AmpGen/CoherentSum.h index 297f4eb65c2..22863b73f68 100644 --- a/AmpGen/CoherentSum.h +++ b/AmpGen/CoherentSum.h @@ -100,7 +100,7 @@ namespace AmpGen std::function evaluator(const EventList_type* = nullptr) const; KeyedFunctors componentEvaluator(const EventList_type* = nullptr) const; - + EventType eventType() const { return m_evtType; } protected: std::vector> m_matrixElements; ///< Vector of matrix elements Bilinears m_normalisations; ///< Normalisation integrals diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index 2c7f86a7961..59ec81e4ccf 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -53,11 +53,11 @@ namespace AmpGen CompiledExpression( const Expression& expression, const std::string& name, const namedArgs&... args ) : CompiledExpressionBase(expression, name) { const MinuitParameterSet* mps = nullptr; - auto process_argument = [&]( const auto& arg ) + auto process_argument = [this, &mps]( const auto& arg ) mutable { if constexpr( std::is_convertible::value ) this->m_db = arg; else if constexpr( std::is_convertible>::value ) this->m_evtMap = arg; - else if constexpr( std::is_convertible::value ) this->m_enableBatch = false; + else if constexpr( std::is_convertible::value ) this->m_enableBatch = false; else if constexpr( std::is_convertible::value ) mps = arg; else if constexpr( std::is_convertible::value ) mps = arg; else if constexpr( std::is_convertible::value ) mps = &arg; diff --git a/AmpGen/PolarisedSum.h b/AmpGen/PolarisedSum.h index 83ec58ccda2..c6aec002e18 100644 --- a/AmpGen/PolarisedSum.h +++ b/AmpGen/PolarisedSum.h @@ -73,6 +73,7 @@ namespace AmpGen const TransitionMatrix& operator[](const size_t& i) const { return m_matrixElements[i] ; } std::function evaluator(const EventList_type* = nullptr) const; KeyedFunctors componentEvaluator(const EventList_type* = nullptr) const; + EventType eventType() const{ return m_eventType; } private: size_t m_nCalls = {0}; real_t m_norm = {1}; diff --git a/CMakeLists.txt b/CMakeLists.txt index f05bc3f941a..2caa58580c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,34 +1,276 @@ ################################################################################ # Package: AmpGen ################################################################################ +cmake_minimum_required(VERSION 3.11.1) +project(AmpGen LANGUAGES CXX VERSION 2.1) -# Support standalone build -if(COMMAND gaudi_subdir) - gaudi_subdir(AmpGen v2r0) - - find_package(ROOT COMPONENTS RIO Hist Matrix Graf Minuit2 Tree MathMore MathCore Physics) - find_package(TBB REQUIRED) - find_package(GSL REQUIRED) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}) - - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp -Wno-unused-parameter -ldl") - set(AmpGen_VERSION_MAJOR "2") - set(AmpGen_VERSION_MINOR "0") - set(AMPGEN_CXX ${CMAKE_CXX_COMPILER} CACHE FILEPATH "This should be the path to compiler (use which c++ for macOS)" ) - configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/AmpGen/Version.h.in" "${CMAKE_CURRENT_SOURCE_DIR}/AmpGen/Version.h") - gaudi_add_library(AmpGen - src/*.cpp - src/Lineshapes/*.cpp - NO_PUBLIC_HEADERS - INCLUDE_DIRS ROOT - LINK_LIBRARIES ROOT TBB GSL) - target_compile_definitions(AmpGen PUBLIC "AMPGEN_CXX=\"${AMPGEN_CXX}\"") - foreach(app Generator Fitter ConvertToSourceCode) - gaudi_add_executable(${app} apps/${app}.cpp - LINK_LIBRARIES AmpGen) - endforeach() +set(AMPGEN_CXX ${CMAKE_CXX_COMPILER} CACHE FILEPATH "This should be the path to compiler (use which c++ for macOS)" ) + +file(TO_CMAKE_PATH "${PROJECT_BINARY_DIR}/CMakeLists.txt" LOC_PATH) +if(EXISTS "${LOC_PATH}") + message(FATAL_ERROR "You cannot build in a source directory (or any directory with a CMakeLists.txt file). Please make a build subdirectory. Feel free to remove CMakeCache.txt and CMakeFiles.") +endif() + +file(GLOB_RECURSE AMPGEN_SRC src/*) +file(GLOB_RECURSE AMPGEN_HDR AmpGen/*) + +set(CMAKE_CXX_STANDARD "17" CACHE STRING "CMAKE_CXX_STANDARD") +set(USE_SIMD "AVX2d" CACHE STRING "USE_SIMD") # AVX instruction set + precision to use +set(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") # flag to use openmp for threading +set(USE_MVEC TRUE CACHE BOOL "USE_MVEC") # flag to use vector math library mvec +set(ENABLE_FITTING TRUE CACHE BOOL "ENABLE_FITTING") # flag to enable fitting (requires Minuit2) + +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/bin") +set(CMAKE_TEST_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/test") + +include(CMakeDependentOption) +include(CMakePrintHelpers) +include(GNUInstallDirs) + +option(AMPGEN_DEBUG "AmpGen Debug printout") +option(AMPGEN_TRACE "AmpGen Trace printout") + +configure_file ("${PROJECT_SOURCE_DIR}/AmpGen/Version.h.in" "${CMAKE_BINARY_DIR}/AmpGenVersion.h") + +add_library(${PROJECT_NAME} SHARED ${AMPGEN_SRC} ${AMPGEN_HDR}) +add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) + +message( STATUS "ROOT_LIBRARIES: ${ROOT_LIBRARIES}") +message( STATUS "GSL_LIBRARIES: ${GSL_LIBRARIES}") + +if(NOT DEFINED ROOT_LIBRARIES) + if(DEFINED ENV{ROOTSYS}) + list(APPEND CMAKE_MODULE_PATH "$ENV{ROOTSYS}/etc/cmake/") + endif() + find_package(ROOT CONFIG REQUIRED COMPONENTS Matrix MathMore MathCore Gpad Tree Graf) +else() + string( REPLACE ":" " " ROOT_LIBRARIES ${ROOT_LIBRARIES}) + separate_arguments(ROOT_LIBRARIES) +endif() + +# if( NOT DEFINED GSL_LIBRARIES ) +# find_package(GSL) +# else() +# string( REPLACE ":" " " GSL_LIBRARIES ${GSL_LIBRARIES}) +# separate_arguments(GSL_LIBRARIES) +# endif() + +if( USE_OPENMP ) + find_package(OpenMP) +endif() + +cmake_print_variables(CMAKE_SOURCE_DIR) + +# Default build type from the Kitware Blog +set(default_build_type "Release") +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "Setting build type to '${default_build_type}' as none was specified.") + set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE + STRING "Choose the type of build." FORCE) + # Set the possible values of build type for cmake-gui + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Release" "MinSizeRel" "RelWithDebInfo") +endif() + +target_include_directories(AmpGen PUBLIC $ + $ ) + +target_include_directories(AmpGen SYSTEM PUBLIC "${ROOT_INCLUDE_DIRS}") + +target_link_libraries(AmpGen PUBLIC -lm "${ROOT_LIBRARIES}" ${CMAKE_DL_LIBS} "${GSL_LIBRARIES}" ) + +find_library(libmvec mvec) + +if ( USE_MVEC AND libmvec ) + message( STATUS "Using libmvec for vectorised math operations") + target_link_libraries(AmpGen PUBLIC mvec) + target_compile_definitions(AmpGen PUBLIC "USE_MVEC=1") +else() + message( STATUS "Warning: libmvec not found, with use scalar math where necessary.") + target_compile_definitions(AmpGen PUBLIC "USE_MVEC=0") +endif() + +if( ENABLE_FITTING ) + if( ( NOT TARGET ROOT::Minuit2 AND NOT TARGET Minuit2 ) OR "${extern_minuit2}" ) + message( STATUS "Use external Minuit2") + add_subdirectory("extern/Minuit2") + set_target_properties(Minuit2 PROPERTIES FOLDER extern) + target_compile_options(Minuit2 PUBLIC -fPIC -Wno-suggest-override) + set_target_properties(Minuit2Math PROPERTIES FOLDER extern) + add_library(ROOT::Minuit2 ALIAS Minuit2) + target_include_directories( AmpGen PUBLIC "${CMAKE_SOURCE_DIR}/extern/Minuit2/inc/") + else() + message( STATUS "Use ROOT::Minuit2") + endif() + if ( TARGET Minuit2 AND NOT TARGET ROOT::Minuit2 ) + find_package( ROOT CONFIG REQUIRED COMPONENTS Minuit2) + add_library(ROOT::Minuit2 ALIAS Minuit2) + endif() + target_link_libraries(AmpGen PUBLIC ROOT::Minuit2 ) +else() + message(STATUS "Disable fitting") +endif() + + +if( USE_OPENMP ) + target_compile_definitions(AmpGen PUBLIC "USE_OPENMP=1") + if(OpenMP_FOUND OR OpenMP_CXX_FOUND) + if(NOT TARGET OpenMP::OpenMP_CXX) + add_library(OpenMP::OpenMP_CXX IMPORTED INTERFACE) + set_property(TARGET OpenMP::OpenMP_CXX PROPERTY INTERFACE_COMPILE_OPTIONS ${OpenMP_CXX_FLAGS}) + set_property(TARGET OpenMP::OpenMP_CXX PROPERTY INTERFACE_LINK_LIBRARIES ${OpenMP_CXX_FLAGS}) + if(CMAKE_VERSION VERSION_LESS 3.4) + set_property(TARGET OpenMP::OpenMP_CXX APPEND PROPERTY INTERFACE_LINK_LIBRARIES -pthread) + else() + find_package(Threads REQUIRED) + set_property(TARGET OpenMP::OpenMP_CXX APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads) + endif() + endif() + target_link_libraries(AmpGen PUBLIC OpenMP::OpenMP_CXX) + else() + message(STATUS "OpenMP not found for CXX, you might have forgotten lb-run ROOT bash or CXX=`which g++` in CERN stack") + endif() +else() + target_compile_definitions(AmpGen PUBLIC "USE_OPENMP=0") +endif() + +if( DEFINED TBB_LIBRARIES ) + target_link_libraries(AmpGen PUBLIC ${TBB_LIBRARIES}) +endif() + +set(RAPIDSIM_DATA "") + +# Default to XROOTD only if on CMT system. Can be overridden with -DAMPGEN_XROOTD=ON +if(DEFINED ENV{CMTCONFIG}) + set(AMPGEN_XROOTD_DEFAULT ON) +else() + set(AMPGEN_XROOTD_DEFAULT OFF) +endif() + +cmake_dependent_option(AMPGEN_XROOTD "Turn on XROOTD discovery" ON "AMPGEN_XROOTD_DEFAULT" OFF) + +if(AMPGEN_XROOTD) + find_library(XROOTD_LIB NAMES libXrdCl.so + HINTS "/cvmfs/lhcb.cern.ch/lib/lcg/releases/LCG_89/xrootd/4.6.0/$ENV{CMTCONFIG}/lib64") + target_link_libraries(AmpGen PUBLIC ${XROOTD_LIB}) +endif() + +target_compile_definitions(AmpGen PRIVATE + "AMPGENROOT_CMAKE=\"${CMAKE_BINARY_DIR}/bin\"" + "AMPGENROOT=\"${PROJECT_SOURCE_DIR}\"" + "AMPGEN_CXX=\"${AMPGEN_CXX}\"" + $<$:DEBUGLEVEL=1> + $<$:TRACELEVEL=1>) + + +target_compile_options(AmpGen + INTERFACE + -Wall -Wextra -Wpedantic -g3 + -Wno-unused-parameter + -Wno-unknown-pragmas + $<$:-O3>) + +if ( ${USE_SIMD} MATCHES "AVX2d" ) + message(STATUS "Enabling AVX2 [double precision]") + target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=1" "ENABLE_AVX2d=1") + target_compile_options(AmpGen PUBLIC -march=native -ftree-vectorize -mavx2 -ffast-math -DHAVE_AVX2_INSTRUCTIONS) +elseif ( ${USE_SIMD} MATCHES "AVX2f" ) + message(STATUS "Enabling AVX2 [single precision]") + target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=1" "ENABLE_AVX2f=1") + target_compile_options(AmpGen PUBLIC -march=native -ftree-vectorize -mavx2 -ffast-math -DHAVE_AVX2_INSTRUCTIONS) +elseif ( ${USE_SIMD} MATCHES "AVX512d" ) + message(STATUS "Enabling AVX2 [double precision]") + target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=1" "ENABLE_AVX512=1") + target_compile_options(AmpGen PUBLIC -march=native -ftree-vectorize -mavx512f -ffast-math -DHAVE_AVX512_INSTRUCTIONS) +else() + target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=0") + target_compile_options(AmpGen PUBLIC -march=x86-64) + message("SIMD disabled, resorting to scalar build : ${USE_SIMD}") +endif() + +if(${CMAKE_CXX_COMPILER_ID} MATCHES "AppleClang" OR + ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" ) + target_compile_options(AmpGen PUBLIC -mfma) +endif() + +if("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" ) + target_link_libraries(AmpGen PUBLIC stdc++ ) + message(STATUS "Using OSX specific flags: -lm -lstdc++ -lSystem") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -lstdc++ -lSystem") +elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + target_link_libraries(AmpGen PUBLIC stdc++) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -lstdc++") else() - cmake_minimum_required(VERSION 3.11.1) - project(AmpGen LANGUAGES CXX VERSION 2.0) - include(Standalone.cmake) + target_compile_options(AmpGen PUBLIC -Wno-suggest-override) endif() + +file(GLOB_RECURSE applications apps/*.cpp examples/*.cpp ) + +foreach( file ${applications} ) + get_filename_component( Executable ${file} NAME_WE ) + add_executable(${Executable}.exe ${file}) + target_compile_options(${Executable}.exe PUBLIC -g3 -Ofast) + target_link_libraries(${Executable}.exe PUBLIC AmpGen ) +endforeach() + +file(GLOB_RECURSE options_files options/*.*) +execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/bin") +foreach(file ${options_files}) + get_filename_component(OptionFile "${file}" NAME) + execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${file}" "${CMAKE_BINARY_DIR}/bin/${OptionFile}") +endforeach() + +enable_testing() +set(Boost_NO_BOOST_CMAKE ON) +add_subdirectory(test) + +include(CMakePackageConfigHelpers) +write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/AmpGenVersion.cmake VERSION ${PACKAGE_VERSION} COMPATIBILITY AnyNewerVersion) + +set(exported_targets_name "${PROJECT_NAME}Targets") +set(exported_targets_filename "${exported_targets_name}.cmake") +set(export_dirpath "lib/cmake/cppuuid") +set(config_basename "${PROJECT_NAME}Config") +set(config_filename "${config_basename}.cmake") +set(version_filename "${config_basename}Version.cmake") + +set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}) +set(LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}) +set(DATA_INSTALL_DIR ${CMAKE_INSTALL_DATADIR}/AmpGen) + +configure_package_config_file(AmpGenConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/AmpGenConfig.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_DATADIR}/AmpGen/cmake + PATH_VARS INCLUDE_INSTALL_DIR LIB_INSTALL_DIR DATA_INSTALL_DIR + ) + +install( FILES ${CMAKE_CURRENT_BINARY_DIR}/AmpGenConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/AmpGenVersion.cmake + DESTINATION ${CMAKE_INSTALL_DATADIR}/AmpGen/cmake) + +install( + TARGETS ${PROJECT_NAME} + EXPORT AmpGenTargets + LIBRARY DESTINATION lib + PUBLIC_HEADER DESTINATION AmpGen +) + +install( + TARGETS AmpGen.exe + DESTINATION bin +) + +install(EXPORT "AmpGenTargets" + NAMESPACE "AmpGen::" + DESTINATION ${CMAKE_INSTALL_DATADIR}/AmpGen/cmake +) + +export( TARGETS AmpGen NAMESPACE AmpGen:: FILE AmpGenTargets.cmake ) +set(CMAKE_EXPORT_PACKAGE_REGISTRY ON) +export(PACKAGE AmpGen) diff --git a/README.md b/README.md index 7b00577c317..6789ffbffdd 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ + + [![Build Status][travis-badge]][travis-link] [![License: LGPL v3][license-badge]](./LICENSE) @@ -24,11 +26,12 @@ Clone with git ``` git clone http://github.com/GooFit/AmpGen/ --recursive ``` -There is at the time of writing only a master branch (FIXME) + ##### Build requirements: * cmake >= 3.11.0 -* C++ compiler with CXX standard >= 17 (gcc >= 8) +* C++ compiler with CXX standard >= 14 (gcc >= 4.9.3, clang ~ 5). + Defaults to Cxx17 (enable cxx14 with cmake flag `-DCMAKE_CXX_STANDARD=14` ) * ROOT >= 6 with MathMore To (re)configure root with these options, use the additional command line options `-Dcxx14 -Dmathmore=ON` when configuring the installation of ROOT. @@ -37,8 +40,7 @@ There is at the time of writing only a master branch (FIXME) * xROOTd for network file access * OpenMP for multithreading * ROOT >= 6 with MathMore and Minuit2 enabled. The external version of Minuit2 provided as an external package of GooFit is used if the ROOT version is not unavailable. - To (re)configure root with these options, use the additional command line options `-Dminuit2=ON -Dmathmore=ON` when configuring the installation of ROOT. -* libmvec for vectorised math operations + To (re)configure root with these options, use the additional command line options `-Dcxx14 -Dminuit2=ON -Dmathmore=ON` when configuring the installation of ROOT. #### Building The configuration of the AmpGen build is performed by cmake. @@ -48,20 +50,17 @@ It is recommended to use a build directory to keep the source tree clean. mkdir build cd build cmake .. -make +make +make install #optional# ``` -This will build the shared library, several standalone test applications, and a set of unit tests. -Several examples of usages of the library are included in the apps directory and are built alongside the library. -All standalone programs can accept both options files and command line arguments. -They also support `--help` to print help for key arguments to the program. -This will also run the program, as arguments can be defined throughout each of the programs rather than all defined at the beginning. +This will build the shared library, several standalone test applications, and a set of unit tests. #### Usage with ROOT The library can be used interactively in conjunction with the ROOT C++ interpreter by adding the following lines to the users root login script -``` +```c++ gSystem->Load("path_to_ampgen/build/lib/libAmpGen.so"); gROOT->ProcessLine(".include path_to_ampgen"); ``` @@ -70,34 +69,36 @@ You can also build AmpGen with LLVM. The only change you might want when using A is to specifically specify the location of the build tool for AmpGen's JIT: ```shell --DAMPGEN_CXX=$(which c++) +-DAMPGEN_CXX=\$(which c++) ``` ##### LXPLUS -In order to build stand-alone on LXPLUS, you will need a valid development environment; the following line will work: +A valid development environment is required to build the library on LXPLUS and similar. The easiest way to provide this is via cvmfs views where available, as this provides the necessary versions of gcc in addition to the ROOT libraries in a coherent manner, which can be used as -```shell +```` source /cvmfs/sft.cern.ch/lcg/views/setupViews.sh LCG_94python3 x86_64-centos7-gcc8-opt -``` -The LCG versions and CMTCONFIG may need to be updated over time. +```` + +The LCG versions and binary tag may need to be updated over time. + +Several examples of usages of the library are included in apps and examples directories and are built alongside the library. All standalone programs can accept both options files and command line arguments. Also supported is the `--help` option to print instructions for key arguments to the program. -#### Using AVX +#### Using SIMD instructions. + +AmpGen (v > 2.0) can be setup to generate vectorised code for faster evaluation of amplitudes / computation of integrals on compatible hardware. Such extensions can be enabled by setting the providing the flag +``` +-DUSE_SIMD=AVX2d +``` +to cmake. This tells AmpGen that code should be generated using the AVX2 instruction set using double precision. Single precision is also supported, but not recommended for fitting. The support for SIMD instructions is often limited on batch systems, and therefore it is often useful to also have a build with these instruction switched off, which can be done using -AmpGen (v > 2.0) can be setup to generate vectorised code for faster evaluation of amplitudes / computation of integrals on compatible hardware. -Such extensions can be enabled by setting the flag ``` -_DUSE_SIMD=AVX2d -``` -Which indicates that code should be generated using the AVX2 instruction set using double precision. -Single precision is also supported, but not recommended for fitting. +-DUSE_SIMD=0 +``` ### Options files and decay descriptors -Options files will generally contain the description of one or more particle decays, -as well as other settings such as input/output locations, global flags such as -whether complex numbers should be interpreted as cartesian or polar, and other parameters -such as the masses and widths of particles is these differ from those given in the PDG. +Options files will generally contain the description of one or more particle decays, as well as other settings such as input/output locations, global flags such as whether complex numbers should be interpreted as cartesian or polar, and other parameters such as the masses and widths of particles is these differ from those given in the PDG. A minimal example options file for the generator application could contain: ``` @@ -106,134 +107,205 @@ EventType D0 K+ pi- pi- pi+ # Fix? Value Step | Fix? Value Step D0{K*(892)0{K+,pi-},rho(770)0{pi+,pi-}} 2 1 0 2 0 0 ``` -The EventType specifies the initial and final states requested by the user. -This gives the ordering of particles used in input data, in output code, and used in internal computations. -This also defines how the amplitude source code must be interfaced with external packages, i.e. MC generators such as EvtGen. +The EventType specifies the initial and final states requested by the user. This gives the ordering of particles used in input data, in output code, and used in internal computations. This also defines how the amplitude source code must be interfaced with external packages, i.e. MC generators such as EvtGen. The decay products of a particle are enclosed within curly braces, for example ``` K*(892)0{K+,pi-} ``` -describes an excited vector kaon decaying into a charged kaon and pion. -For more details about the API for describing particle decays, see [AmpGen::Particle](https://goofit.github.io/AmpGen/de/dd7/class_amp_gen_1_1_particle.html) -The other numbers on the lines that describe the decays parameterise the coupling to this channel, -either in terms of real and imaginary parts or an amplitude and a phase. -Each parameter is specified in terms of three numbers: the _fix_ flag, the initial value, and the step size. +describes an excited vector kaon decaying into a charged kaon and pion. For more details about the API for describing particle decays, see [AmpGen::Particle](https://goofit.github.io/AmpGen/de/dd7/class_amp_gen_1_1_particle.html) The other numbers on the lines that describe the decays parameterise the coupling to this channel, +either in terms of real and imaginary parts or an amplitude and a phase. Each parameter is specified in terms of three numbers: the _fix_ flag, the initial value, and the step size. The possible options for the _fix_ flag are: + * Free (fix=0) and a step size of not 0. * Fixed (fix=2, for historical reasons) * Compile-Time-Constant (fix=3) which indicates that the parameter should be treated as a (JIT) compile time constant, which in some cases allows for more aggressive optimisations to be performed. -These options can be used in the Generator application, which is described below. +These options can be used in the AmpGen application, which is described below. Decays can either be specified fully inline, as above, or split into multiple steps, which is useful for treating the so called _cascade_ decays, an example of which is shown below. ``` D0{K(1)(1270)+,pi-} 0 1 0.1 0 0 0.1 - +Type K(1)(1270)+{rho(770)0{pi+,pi-},K+} 2 1 0 2 0 0 K(1)(1270)+{K*(892)0{K+,pi-},pi+} 0 1 0.1 0 0 0.1 ``` -The production/decay couplings of the resonance are now defined in terms of the coupling to the channel, -which can be useful in making comparisons between different production modes of a resonance. -Additional care must be taken in such a case to not introduce redundant degrees of freedom. +The production/decay couplings of the resonance are now defined in terms of the coupling to the channel, which can be useful in making comparisons between different production modes of a resonance. Additional care must be taken in such a case so as not to introduce redundant degrees of freedom. -Configuration can be split over multiple files by the using _Import_ keyword, for example, to import the parameters for the isoscalar K-matrix, the line +Configuration can be split over multiple files by the using _Import_ keyword, for example, to import the parameters for the parameters associated with the isoscalar K-matrix, the line ``` -Import $AMPGENROOT/options/kMatrix.opt +Import \$AMPGENROOT/options/kMatrix.opt ``` can be added to options file. Multiple user configuration files can also be specified by including multiple files on the command line. +#### PDF Types + +AmpGen supports several different types of probability density functions (PDFs), which are detailed in this section. + +##### CoherentSum + +The most common type of PDF is the CoherentSum. In this case, the total amplitude is given by the sum of amplitudes, weighted by complex coefficients. At a position in the phase space , the transition amplitude is given by: + + + +and the corresponding probability density is proportional to . The CoherentSum is the default amplitude in many cases, and is used to describe the decay of a single, (pseudo)scalar particle to two or more (pseudo)scalar decay products. + +##### PolarisedSum + +The initial and/or final state(s) may also carry spin, in which case the spin states must also be summed. The transition matrix can be written in the isobar model as + + , + +where and label the initial and final states, respectively. As these states are in principal observables, the indices related to spin must be summed incoherently. The probability density function in this case is therefore given by + + , + +where is the relevant density matrix for the initial state, which is given by 1 for a scalar initial state. For a spin- state, the density matrix can be parameterised in terms of a polarisation vector and the Pauli matrices , and is given by: + + + +For a spin-1 initial state, the density matrix is parameterised in terms of the Gell-Mann matrices, , as + + , + +where now the polarisation 'vector' has 8 components. + +##### IncoherentSum + +An alternative model is the IncoherentSum, which may be useful to describe the probability density of a background contribution that contains incoherent sources with several different resonances. Generally, such models are only useful for relatively small backgrounds in relatively pure samples, as in general background contributions cannot be described with such a simple parameterisation. In this case, the probability is given by an incoherent sum of amplitudes: + + + ## Applications -This section details the prebuilt command line applications that use the AmpGen library for some common functionality, such as generating Toy Monte Carlo samples -and debugging amplitudes. + +This section details the prebuilt command line applications that use the AmpGen library for some common functionality, such as generating Toy Monte Carlo samples and debugging amplitudes. ### Table of contents -* [Generator](#generator) +* [AmpGen](#AmpGen) * [Debugger](#debugger) -* [ConvertToSourceCode](#converttosourcecode) +* [LibDiff](#LibDiff) +* [DataConverter](#DataConverter) -### Generator +### AmpGen -The standalone generator for models can be used as +The standalone generator (named AmpGen) is used as: ```shell -Generator MyOpts.opt --nEvents=10000 --Output=output.root +AmpGen.exe MyOpts.opt --nEvents=10000 --Output=output.root ``` -Which generates 10000 events of the model described in MyOpts.opt and saves them to output.root. -The output should include a tree (DalitzEventList) of candidates with the full four-vectors, as well as one- and two-dimensional projections, an example of which is shown below: +where MyOpts.opt contains the options described in the previous section that describe the decay the user wishes to generate, and the optional arguments `nEvents` and `Output` given the number of events requested and the output file, respectively. The full list of application specific arguments can be obtained by: -![s01](doc/figs/s01.png) +```bash +AmpGen.exe --help +``` -In particular, the tree indicates the way in which data is by default loaded into the _Event_ / _EventList_ class. -Several models for different decays published by the LHCb collaboration are included in the options directory. These options do not include EventTypes so as they can be included as part of a larger decay chain if required. For example, to generate toy events: +The output includes a tree (DalitzEventList) of candidates with the full four-vectors, as well as one- and two-dimensional projections, an example of which is shown below: -``` -./Generator options/D02Kpipipi.opt --EventType "D0 K- pi+ pi+ pi-" --nEvents 1000000 +

+ +

+ +Several models for different decays published by the LHCb collaboration are included in the options directory, in addition to several other decay modes to demonstrate different features. These options often do not include EventTypes so as they can be included as part of a larger decay chain if required. For example, to generate toy decays, the type of the events requested must also be specified: + +```shell +AmpGen.exe options/D02Kpipipi.opt --EventType "D0 K- pi+ pi+ pi-" --nEvents 1000000 ``` -### Debugger +The standalone generator can also be used to only produce the source code that evaluates the amplitude, to be used by other generators such as EvtGen. In this case, the PDF is automatically normalised such that . The code can be generated and compiled into a shared library as follows +```shell +AmpGen.exe MyOpts.opt --Output=MyModel.cpp --SourceOnly +g++ -Ofast -shared -rdynamic --std=c++14 -fPIC MyModel.cpp -o MyModel.so +``` +Decays can also be specified entirely on the command line in order to quickly study the distributions of different decay modes. For example, to generate a sample of 10000 decays, -The debugger application is a tool for producing verbose information debugging for amplitudes and models. It is used on an options file as +```shell +AmpGen.exe --Decay "Lambda(b)0{p+,K*(892)bar-{K-,pi0}}" --nEvents 10000 --Type PolarisedSum ``` -./Debugger MyOpts.opt + +The flag `Type` is used to specify that the initial and/or final states includes at least one particle carrying spin, and thus polarisation must be taken into account. The output is both the full event kinematics, as well as projections of the different invariant masses shown below: + +

+

+ + +
+

+ +#### Phase space generators + +Generating events consists of two phases. Firstly, the kinematics of candidates are generated according to some distribution, by default uniform in the phase space. The target distribution, , is then obtained using the accept-reject method. A candidate generated at position in the phase space is retained on the condition that + + , + +where is the largest possible value of , and is a random number uniformly drawn between 0 and 1. + +​ The generation can be made more efficient by making the first step produce candidates that are distributed more closely to the full distribution than the uniform phase space. In particular, this is relevant for producing very narrow structures such as the resonance efficiently. To use this option, the flag `PhaseSpace` should be set to the value `TreePhaseSpace`. For example, to generate a sample of decays: + +```shell +AmpGen.exe --Decay "Lambda(b)0{J/psi0{mu+,mu-},Lambda(1405)0{p+,pi-}}" --nEvents 1000000 --Type PolarisedSum --PhaseSpace TreePhaseSpace ``` -which calculates each amplitude at a randomly generated point in phase space, as well as calculating the total amplitude accounting for complex -couplings. Also computed is the amplitude for the P conjugate event. A more useful application is the _verbose_ debugging mode which can be -activated by + +Two example projections are shown below, of the dimuon invariant mass with essentially no width, which would be virtually impossible to generate with a uniform distribution and the naive accept-reject method, and the combined mass of the dimuon with the proton from the decay: + +

+

+ + +
+

+ +### Debugger + +The debugger application is a tool for producing verbose information debugging for amplitudes and models. It is used on an options file as + ``` -./Debugger MyOpts.opt --CoherentSum::Debug +Debugger.exe MyOpts.opt ``` -which produces a large number of intermediate steps in the calculation of each amplitude, which are added to the calculation using the -ADD_DEBUG and ADD_DEBUG_TENSOR macros in the code generation. For example, in src/Lineshapes/BW.cpp. -(n.b), if the model is a PolarisedSum, i.e. handles spin in the initial/final state, the flag PolarisedSum::Debug should be used instead of CoherentSum::Debug, in order -to generate all of the intermediate calculations of the amplitude. +which calculates each amplitude at a randomly generated point in phase space, as well as calculating the total amplitude accounting for complex couplings. -### ConvertToSourceCode +A more useful application is the _verbose_ debugging mode which can be activated by -This produces source code to evaluate the PDF, and normalises for use with other generators such as EvtGen, i.e. P(max) < 1. This can be used as -```shell -./ConvertToSourceCode MyOpts.opt --Output=MyFile.cpp ``` -This can then be a compiled to a shared library using -```shell -g++ -Ofast -shared -rdynamic --std=c++14 -fPIC MyFile.cpp -o MyFile.so +Debugger.exe MyOpts.opt --CoherentSum::Debug ``` +which produces a large number of intermediate steps in the calculation of each amplitude, which are added to the calculation using the ADD_DEBUG and ADD_DEBUG_TENSOR macros in the code generation. For example, in src/Lineshapes/BW.cpp. +If the model is a PolarisedSum, i.e. handles spin in the initial/final state, the flag PolarisedSum::Debug should be used instead of CoherentSum::Debug. + +### LibDiff + +### DataConvertor ## Examples ### SignalOnlyFitter -An example fitter is provided in _examples/SignalOnlyFitter.cpp_, which as the name suggests only has a single signal component in the fit. -The free parameters of the fit are specified in the same way as the Generator, -with the additional relevant slots being _DataSample_ which specifies the signal sample to fit, -which is presumed to already have the selection applied, and _Branches_ which takes a list of branch names, -and defaults to the format used by the Generator etc. More details can be found with -``` -SignalOnlyFitter --help +An example fitter is provided in _examples/SignalOnlyFitter.cpp_, which as the name suggests only has a single signal component in the fit. The free parameters of the fit are specified in the same way as the Generator, with the additional relevant slots being _DataSample_ which specifies the signal sample to fit, which is presumed to already have the selection applied, and _Branches_ which takes a list of branch names, and defaults to the format used by the Generator. More details can be found with +```shell +SignalOnlyFitter.exe --help ``` For example, the fitter can be used to fit a toy MC sample generated by the generator by running: -``` -Generator MyOpts.opt --nEvents 100000 -SignalOnlyFitter MyOpts.opt --DataSample Generate_Output.root +```shell +AmpGen.exe MyOpts.opt --nEvents 100000 +SignalOnlyFitter.exe MyOpts.opt --DataSample Generate_Output.root ``` ## Advanced -This section contains miscellaneous details on more advanced functionality, including using python bindings and alternative parameterisation of the spin factors. +This section contains miscellaneous details on more advanced functionality, including using python bindings and alternative parameterisations of the spin factors. ### Table of contents * [Python Bindings](#python-bindings) * [Particle Properties and Lineshape parameters](#particle-properties-and-lineshape-parameters) * [Fit parameters and expressions](#fit-parameters-and-expressions) * [Spin Formalisms](#spin-formalisms) -* [Quasi-Particles](#quasi-particles) +* [Quasiparticles](#quasiparticles) ### Python Bindings Models built into a shared library can be used in python using the following flags into ConvertToSourceCode: ```shell -./ConvertToSourceCode MyOpts.opt --Output=MyFile.cpp --OutputEvents=events.csv --IncludePythonBindings +./AmpGen.exe MyOpts.opt --Output=MyFile.cpp --SourceOnly --OutputEvents=events.csv --IncludePythonBindings ``` where normalisation events are also output for testing purposes in events.csv. This can then be used with the python bindings in ampgen.py: @@ -251,7 +323,7 @@ fcn2 = data.apply(model.FCN, axis=1) ``` ### Particle Properties and Lineshape parameters -The particles available and their default properties can be found in *options/mass\_width.csv* using the MC format of the 2008 PDG. Additional pseudoparticles, such as nonresonant states and terms for use in conjunction with K-matrices are defined by *options/MintDalitzSpecialParticles.csv*. Any additional user defined particles should be added here. For the default lineshape (the relavistic Breit-Wigner or BW), there are three parameters: The mass, the width and the Blatt-Weisskopf radius. These default to their PDG values, but can be overridden in the options file with parameters: *particleName*\_mass, *particleName*\_width, *particleName*\_radius. To vary the mass of the meson, the line: +The particles available and their default properties can be found in *options/mass\_width.csv* using the MC format of the 2008 PDG. Additional pseudoparticles, such as nonresonant states and terms for use in conjunction with K-matrices are defined by *options/MintDalitzSpecialParticles.csv*. Any additional user defined particles should be added here. For the default lineshape (the relavistic Breit-Wigner or BW), there are three parameters: The mass, the width and the Blatt-Weisskopf radius. These default to their PDG values, but can be overridden in the options file with parameters: *particleName*\_mass, *particleName*\_width, *particleName*\_radius. To vary the mass of the meson, the line: ``` K(1)(1270)+_mass 0 1.270 0.01 ``` @@ -262,20 +334,20 @@ Other lineshapes may define other parameters, for example channel couplings or p Parameters can either be specified by three parameters, in the case of a scalar parameter such as a mass or a width, or with six parameters in the case of a complex parameter such as a coupling. Upper and lower bounds on parameters can also be set by specifying a parameter with five parameters or ten parameters for a scalar or complex, respectively. -For example, if we wished to vary the mass of the meson in the above example, but restricting the allowed values in the range : +For example, if we wished to vary the mass of the meson in the above example, but restricting the allowed values in the range : ``` K(1)(1270)+_mass 0 1.27 0.01 0.0 2.0 ``` Parameters can also be related to each other via expressions, -Suppose for example we have and in the same fit (for example, for ) -The properties of one can be allowed to vary, for example the , and the other fixed to the same value, using: +Suppose for example we have and in the same fit (for example, in ) +The properties of one can be allowed to vary, for example the , and the other fixed to the same value, using: ``` K(1)(1270)+_mass 0 1.27 0.01 0.0 2.0 K(1)(1270)bar-_mass = K(1)(1270)+_mass ``` Parameter expressions are whitespace delimited due to the abundance of **odd** glyphs such as brackets and +/- in the names of parameters. -Expressions support the binary operations , as well as common unary functions such as sqrt, trigonometric functions etc. +Expressions support the binary operations , as well as common unary functions such as sqrt, trigonometric functions etc. ### Spin Formalisms @@ -283,14 +355,14 @@ AmpGen implements both the covariant tensor (or Rarita-Schwinger) and canonical Both formalisms refer to states of well-defined orbital angular momentum, as opposed to the helicity states, as the states with well-defined orbital angular momentum have a straightforward parity and momentum dependences. The default formalism is the covariant tensor formalism, but this can be switched to the canonical formalism changing the flag ``` -Particle::SpinFormalism Canonical ## default = Covariant +Particle::SpinFormalism Canonical ``` in the options file. The spin formalism for an individual decay chain can be specified by changing the attribute SpinFormalism in the decay descriptor. For example, ``` D0[SpinFormalism=Canonical]{K*(892)bar0,rho(770)0} ``` -selects the S-wave of the system. The user can also specify systems of helicity couplings in the canonical formalism, using the attribute _helAmp_. For example, suppose the transversity amplitudes were used rather than the canonical, then the user can specify +selects the S-wave of the system. The user can also specify systems of helicity couplings in the canonical formalism, using the attribute _helAmp_. For example, suppose the transversity amplitudes were used rather than the canonical, then the user can specify ``` D0[SpinFormalism=Canonical;helAmp=Long]{K*(892)bar0,rho(770)0} D0[SpinFormalism=Canonical;helAmp=t1]{K*(892)bar0,rho(770)0} @@ -312,11 +384,29 @@ t2 { -0.707106781 -1 -1 } ``` -That is specified as sets of three numbers, firstly the coupling, and then the two particle helicities. So in this example, the longitudinal amplitude is the helicity state, while the two transverse amplitudes and the sum and difference of the two other helicity amplitudes. +That is specified as sets of three numbers, firstly the coupling, and then the two particle helicities. So in this example, the longitudinal amplitude is the helicity state, while the two transverse amplitudes and the sum and difference of the two other helicity amplitudes. -### Quasi-Particles +### Quasiparticles +Quasiparticles are fictional decaying particles that can be implemented in the decay chain for a variety of different purposes. The original use case was to group some amplitudes with the same quantum numbers with couplings that want to be factorised. +For example, for the -wave, the K matrix description may be used. The coupling from the initial state may be written as +``` +D0{K0S0,NonResS0} ... +``` +The quasiparticle _NonResS0_ can then be decayed to the final state via the K matrix lineshape(s) +``` +NonResS0[kMatrix.pole.0]{pi+,pi-} ... +NonResS0[kMatrix.pole.1]{pi+,pi-} ... +... +``` +where each of the .X is one of the terms of the (pole) production vector. +In this example, an equivalent formulation would be +``` +D0{K0S0,NonResS0[kMatrix.pole.0]{pi+,pi-}} ... +D0{K0S0,NonResS0[kMatrix.pole.1]{pi+,pi-}} ... +... +``` ## Acknowledgements The development of this software has been supported by the National Science Foundation under grant PHY-1414736 and through a subcontract under Cooperative Agreement OAC-1836650. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the developers and do not necessarily reflect the views of the National Science Foundation. diff --git a/README.tex.md b/README.tex.md index 46878dc36b6..7f4daedb2a6 100644 --- a/README.tex.md +++ b/README.tex.md @@ -1,3 +1,5 @@ + + [![Build Status][travis-badge]][travis-link] [![License: LGPL v3][license-badge]](./LICENSE) @@ -24,7 +26,7 @@ Clone with git ``` git clone http://github.com/GooFit/AmpGen/ --recursive ``` -There is at the time of writing only a master branch (FIXME) + ##### Build requirements: * cmake >= 3.11.0 @@ -48,16 +50,17 @@ It is recommended to use a build directory to keep the source tree clean. mkdir build cd build cmake .. -make +make +make install #optional# ``` -This will build the shared library, several standalone test applications, and a set of unit tests. +This will build the shared library, several standalone test applications, and a set of unit tests. #### Usage with ROOT The library can be used interactively in conjunction with the ROOT C++ interpreter by adding the following lines to the users root login script -``` +```c++ gSystem->Load("path_to_ampgen/build/lib/libAmpGen.so"); gROOT->ProcessLine(".include path_to_ampgen"); ``` @@ -66,41 +69,36 @@ You can also build AmpGen with LLVM. The only change you might want when using A is to specifically specify the location of the build tool for AmpGen's JIT: ```shell --DAMPGEN_CXX=$(which c++) +-DAMPGEN_CXX=\$(which c++) ``` ##### LXPLUS -In order to build stand-alone on LXPLUS, you will need a valid development environment; the following line will work: +A valid development environment is required to build the library on LXPLUS and similar. The easiest way to provide this is via cvmfs views where available, as this provides the necessary versions of gcc in addition to the ROOT libraries in a coherent manner, which can be used as -```shell -lb-run -c x86_64-centos7-gcc62-opt ROOT $SHELL -``` -Additionally, the ROOT versions installed on cvfms generally require C++17 support when building. +```` +source /cvmfs/sft.cern.ch/lcg/views/setupViews.sh LCG_94python3 x86_64-centos7-gcc8-opt +```` + +The LCG versions and binary tag may need to be updated over time. -Several examples of usages of the library are included in the apps directory and are -built alongside the library. -All standalone programs can accept both options files and command line arguments. -They also support `--help` to print help for key arguments to the program. -This will also run the program, as arguments can be defined throughout each of the programs rather than all defined at the beginning. +Several examples of usages of the library are included in apps and examples directories and are built alongside the library. All standalone programs can accept both options files and command line arguments. Also supported is the `--help` option to print instructions for key arguments to the program. #### Using SIMD instructions. -AmpGen (v > 2.0) can be setup to generate vectorised code for faster evaluation of amplitudes / computation of integrals on compatible hardware. -Such extensions can be enabled by setting the flag +AmpGen (v > 2.0) can be setup to generate vectorised code for faster evaluation of amplitudes / computation of integrals on compatible hardware. Such extensions can be enabled by setting the providing the flag ``` -_DUSE_SIMD=AVX2d -``` -Which indicates that code should be generated using the AVX2 instruction set using double precision. -Single precision is also supported, but not recommended for fitting. +-DUSE_SIMD=AVX2d +``` +to cmake. This tells AmpGen that code should be generated using the AVX2 instruction set using double precision. Single precision is also supported, but not recommended for fitting. The support for SIMD instructions is often limited on batch systems, and therefore it is often useful to also have a build with these instruction switched off, which can be done using +``` +-DUSE_SIMD=0 +``` ### Options files and decay descriptors -Options files will generally contain the description of one or more particle decays, -as well as other settings such as input/output locations, global flags such as -whether complex numbers should be interpreted as cartesian or polar, and other parameters -such as the masses and widths of particles is these differ from those given in the PDG. +Options files will generally contain the description of one or more particle decays, as well as other settings such as input/output locations, global flags such as whether complex numbers should be interpreted as cartesian or polar, and other parameters such as the masses and widths of particles is these differ from those given in the PDG. A minimal example options file for the generator application could contain: ``` @@ -109,130 +107,193 @@ EventType D0 K+ pi- pi- pi+ # Fix? Value Step | Fix? Value Step D0{K*(892)0{K+,pi-},rho(770)0{pi+,pi-}} 2 1 0 2 0 0 ``` -The EventType specifies the initial and final states requested by the user. -This gives the ordering of particles used in input data, in output code, and used in internal computations. -This also defines how the amplitude source code must be interfaced with external packages, i.e. MC generators such as EvtGen. +The EventType specifies the initial and final states requested by the user. This gives the ordering of particles used in input data, in output code, and used in internal computations. This also defines how the amplitude source code must be interfaced with external packages, i.e. MC generators such as EvtGen. The decay products of a particle are enclosed within curly braces, for example ``` K*(892)0{K+,pi-} ``` -describes an excited vector kaon decaying into a charged kaon and pion. -For more details about the API for describing particle decays, see [AmpGen::Particle](https://goofit.github.io/AmpGen/de/dd7/class_amp_gen_1_1_particle.html) -The other numbers on the lines that describe the decays parameterise the coupling to this channel, -either in terms of real and imaginary parts or an amplitude and a phase. -Each parameter is specified in terms of three numbers: the _fix_ flag, the initial value, and the step size. +describes an excited vector kaon decaying into a charged kaon and pion. For more details about the API for describing particle decays, see [AmpGen::Particle](https://goofit.github.io/AmpGen/de/dd7/class_amp_gen_1_1_particle.html) The other numbers on the lines that describe the decays parameterise the coupling to this channel, +either in terms of real and imaginary parts or an amplitude and a phase. Each parameter is specified in terms of three numbers: the _fix_ flag, the initial value, and the step size. The possible options for the _fix_ flag are: + * Free (fix=0) and a step size of not 0. * Fixed (fix=2, for historical reasons) * Compile-Time-Constant (fix=3) which indicates that the parameter should be treated as a (JIT) compile time constant, which in some cases allows for more aggressive optimisations to be performed. -These options can be used in the Generator application, which is described below. +These options can be used in the AmpGen application, which is described below. Decays can either be specified fully inline, as above, or split into multiple steps, which is useful for treating the so called _cascade_ decays, an example of which is shown below. ``` D0{K(1)(1270)+,pi-} 0 1 0.1 0 0 0.1 - +Type K(1)(1270)+{rho(770)0{pi+,pi-},K+} 2 1 0 2 0 0 K(1)(1270)+{K*(892)0{K+,pi-},pi+} 0 1 0.1 0 0 0.1 ``` -The production/decay couplings of the @f$K_1(1270)^+@f$ resonance are now defined in terms of the coupling to the @f$\rho(770)^0 K^+@f$ channel, -which can be useful in making comparisons between different production modes of a resonance. -Additional care must be taken in such a case to not introduce redundant degrees of freedom. +The production/decay couplings of the $K_1(1270)^+$ resonance are now defined in terms of the coupling to the $\rho(770)^0 K^+$ channel, which can be useful in making comparisons between different production modes of a resonance. Additional care must be taken in such a case so as not to introduce redundant degrees of freedom. -Configuration can be split over multiple files by the using _Import_ keyword, for example, to import the parameters for the isoscalar K-matrix, the line +Configuration can be split over multiple files by the using _Import_ keyword, for example, to import the parameters for the parameters associated with the isoscalar K-matrix, the line ``` -Import $AMPGENROOT/options/kMatrix.opt +Import \$AMPGENROOT/options/kMatrix.opt ``` can be added to options file. Multiple user configuration files can also be specified by including multiple files on the command line. +#### PDF Types + +AmpGen supports several different types of probability density functions (PDFs), which are detailed in this section. + +##### CoherentSum + +The most common type of PDF is the CoherentSum. In this case, the total amplitude is given by the sum of amplitudes, weighted by complex coefficients. At a position in the phase space $\mathbf{x}$, the transition amplitude $\mathcal{T}$ is given by: + +$\mathcal{T}(\mathbf{x}) = \sum_{k} g_k A_k (\mathbf{x})$ + +and the corresponding probability density is proportional to $\mathcal{P}(\mathbf{x})\propto \left|\mathcal{T}(\mathbf{x})\right|^2$. The CoherentSum is the default amplitude in many cases, and is used to describe the decay of a single, (pseudo)scalar particle to two or more (pseudo)scalar decay products. + +##### PolarisedSum + +The initial and/or final state(s) may also carry spin, in which case the spin states must also be summed. The transition matrix can be written in the isobar model as + +$\mathcal{T}_{if} = \sum_k g_k \mathcal{T}^{k}_{if}(\mathbf{x})$, + +where $i$ and $f$ label the initial and final states, respectively. As these states are in principal observables, the indices related to spin must be summed incoherently. The probability density function in this case is therefore given by + +$\mathcal{P}(\mathbf{x}) = \sum_{if} \hat{\rho}_{ij} T_{if}(\mathbf{x}) T^{*}_{jf}(\mathbf{x}) $, + +where $\hat{\rho}$ is the relevant density matrix for the initial state, which is given by 1 for a scalar initial state. For a spin-$\frac{1}{2}$ state, the density matrix can be parameterised in terms of a polarisation vector $p_i$ and the Pauli matrices $\sigma_i$, and is given by: + +$\hat{\rho} = I + \sigma_i p_i$ + +For a spin-1 initial state, the density matrix is parameterised in terms of the Gell-Mann matrices, $\lambda_k$, as + +$\hat{\rho} = I + \lambda_k p_k$, + +where now the polarisation 'vector' $p_k$ has 8 components. + +##### IncoherentSum + +An alternative model is the IncoherentSum, which may be useful to describe the probability density of a background contribution that contains incoherent sources with several different resonances. Generally, such models are only useful for relatively small backgrounds in relatively pure samples, as in general background contributions cannot be described with such a simple parameterisation. In this case, the probability is given by an incoherent sum of amplitudes: + +$\mathcal{P}(\mathbf{x}) = \sum_k g_k^2 \left| A_k \right|^2 $ + ## Applications -This section details the prebuilt command line applications that use the AmpGen library for some common functionality, such as generating Toy Monte Carlo samples -and debugging amplitudes. + +This section details the prebuilt command line applications that use the AmpGen library for some common functionality, such as generating Toy Monte Carlo samples and debugging amplitudes. ### Table of contents -* [Generator](#generator) +* [AmpGen](#AmpGen) * [Debugger](#debugger) -* [ConvertToSourceCode](#converttosourcecode) +* [LibDiff](#LibDiff) +* [DataConverter](#DataConverter) -### Generator +### AmpGen -The standalone generator for models can be used as +The standalone generator (named AmpGen) is used as: ```shell -Generator MyOpts.opt --nEvents=10000 --Output=output.root +AmpGen.exe MyOpts.opt --nEvents=10000 --Output=output.root ``` -Which generates 10000 events of the model described in MyOpts.opt and saves them to output.root. -The output should include a tree (DalitzEventList) of candidates with the full four-vectors, as well as one- and two-dimensional projections, an example of which is shown below: +where MyOpts.opt contains the options described in the previous section that describe the decay the user wishes to generate, and the optional arguments `nEvents` and `Output` given the number of events requested and the output file, respectively. The full list of application specific arguments can be obtained by: + +```bash +AmpGen.exe --help +``` + +The output includes a tree (DalitzEventList) of candidates with the full four-vectors, as well as one- and two-dimensional projections, an example of which is shown below:

- +

-In particular, the tree indicates the way in which data is by default loaded into the _Event_ / _EventList_ class. -Several models for different @f$D^0@f$ decays published by the LHCb collaboration are included in the options directory. These options do not include EventTypes so as they can be included as part of a larger decay chain if required. For example, to generate @f$10^6@f$ toy @f$D^{0}\to K^{-} \pi^+ \pi^+ \pi^- @f$ events: +Several models for different $D^0$ decays published by the LHCb collaboration are included in the options directory, in addition to several other decay modes to demonstrate different features. These options often do not include EventTypes so as they can be included as part of a larger decay chain if required. For example, to generate $10^6$ toy $\Dz\to\Km\pip\pip\pim$ decays, the type of the events requested must also be specified: +```shell +AmpGen.exe options/D02Kpipipi.opt --EventType "D0 K- pi+ pi+ pi-" --nEvents 1000000 ``` -./Generator options/D02Kpipipi.opt --EventType "D0 K- pi+ pi+ pi-" --nEvents 1000000 + +The standalone generator can also be used to only produce the source code that evaluates the amplitude, to be used by other generators such as EvtGen. In this case, the PDF is automatically normalised such that $\mathcal{P}_{\text{max}} < 1$ . The code can be generated and compiled into a shared library as follows +```shell +AmpGen.exe MyOpts.opt --Output=MyModel.cpp --SourceOnly +g++ -Ofast -shared -rdynamic --std=c++14 -fPIC MyModel.cpp -o MyModel.so ``` +Decays can also be specified entirely on the command line in order to quickly study the distributions of different decay modes. For example, to generate a sample of 10000 $\Lambda_b \to p K^{*-}$ decays, + +```shell +AmpGen.exe --Decay "Lambda(b)0{p+,K*(892)bar-{K-,pi0}}" --nEvents 10000 --Type PolarisedSum +``` + +The flag `Type` is used to specify that the initial and/or final states includes at least one particle carrying spin, and thus polarisation must be taken into account. The output is both the full event kinematics, as well as projections of the different invariant masses shown below: + +

+

+ + +
+

#### Phase space generators -Generating events consists of two phases. Firstly, the kinematics of candidates are generated according to some distribution, typically flat in the phase space. -The target distribution is then obtained using the accept-reject method, that is, for a candidate at position @$f +Generating events consists of two phases. Firstly, the kinematics of candidates are generated according to some distribution, by default uniform in the phase space. The target distribution, $\mathcal{P}(\mathbf{x})$ , is then obtained using the accept-reject method. A candidate generated at position $\mathbf{x}$ in the phase space is retained on the condition that + $\mathcal{P}(\mathbf{x}) > \mathcal{P}_{\text{max}} \times \texttt{Uniform}(0,1) $, -### Debugger +where $\mathcal{P}_{\text{max}}$ is the largest possible value of $\mathcal{P}(\mathbf{x})$ , and $\texttt{Uniform}(0,1)$ is a random number uniformly drawn between 0 and 1. -The debugger application is a tool for producing verbose information debugging for amplitudes and models. It is used on an options file as -``` -./Debugger MyOpts.opt +​ The generation can be made more efficient by making the first step produce candidates that are distributed more closely to the full distribution than the uniform phase space. In particular, this is relevant for producing very narrow structures such as the $J/\psi$ resonance efficiently. To use this option, the flag `PhaseSpace` should be set to the value `TreePhaseSpace`. For example, to generate a sample of $10^6$ $\Lambda_b^0 \to J/\psi \left[\mu^+\mu^-\right]\Lambda(1405)^0 \left[p^+ \pi^-\right]$ decays: + +```shell +AmpGen.exe --Decay "Lambda(b)0{J/psi0{mu+,mu-},Lambda(1405)0{p+,pi-}}" --nEvents 1000000 --Type PolarisedSum --PhaseSpace TreePhaseSpace ``` -which calculates each amplitude at a randomly generated point in phase space, as well as calculating the total amplitude accounting for complex -couplings. Also computed is the amplitude for the P conjugate event. A more useful application is the _verbose_ debugging mode which can be -activated by + +Two example projections are shown below, of the dimuon invariant mass with essentially no width, which would be virtually impossible to generate with a uniform distribution and the naive accept-reject method, and the combined mass of the dimuon with the proton from the $\Lambda(1405)^0$ decay: + +

+

+ + +
+

+ +### Debugger + +The debugger application is a tool for producing verbose information debugging for amplitudes and models. It is used on an options file as + ``` -./Debugger MyOpts.opt --CoherentSum::Debug +Debugger.exe MyOpts.opt ``` -which produces a large number of intermediate steps in the calculation of each amplitude, which are added to the calculation using the -ADD_DEBUG and ADD_DEBUG_TENSOR macros in the code generation. For example, in src/Lineshapes/BW.cpp. -(n.b), if the model is a PolarisedSum, i.e. handles spin in the initial/final state, the flag PolarisedSum::Debug should be used instead of CoherentSum::Debug, in order -to generate all of the intermediate calculations of the amplitude. +which calculates each amplitude at a randomly generated point in phase space, as well as calculating the total amplitude accounting for complex couplings. -### ConvertToSourceCode +A more useful application is the _verbose_ debugging mode which can be activated by -This produces source code to evaluate the PDF, and normalises for use with other generators such as EvtGen, i.e. P(max) < 1. This can be used as -```shell -./ConvertToSourceCode MyOpts.opt --Output=MyFile.cpp ``` -This can then be a compiled to a shared library using -```shell -g++ -Ofast -shared -rdynamic --std=c++14 -fPIC MyFile.cpp -o MyFile.so +Debugger.exe MyOpts.opt --CoherentSum::Debug ``` +which produces a large number of intermediate steps in the calculation of each amplitude, which are added to the calculation using the ADD_DEBUG and ADD_DEBUG_TENSOR macros in the code generation. For example, in src/Lineshapes/BW.cpp. +If the model is a PolarisedSum, i.e. handles spin in the initial/final state, the flag PolarisedSum::Debug should be used instead of CoherentSum::Debug. + +### LibDiff + +### DataConvertor ## Examples ### SignalOnlyFitter -An example fitter is provided in _examples/SignalOnlyFitter.cpp_, which as the name suggests only has a single signal component in the fit. -The free parameters of the fit are specified in the same way as the Generator, -with the additional relevant slots being _DataSample_ which specifies the signal sample to fit, -which is presumed to already have the selection applied, and _Branches_ which takes a list of branch names, -and defaults to the format used by the Generator etc. More details can be found with -``` -SignalOnlyFitter --help +An example fitter is provided in _examples/SignalOnlyFitter.cpp_, which as the name suggests only has a single signal component in the fit. The free parameters of the fit are specified in the same way as the Generator, with the additional relevant slots being _DataSample_ which specifies the signal sample to fit, which is presumed to already have the selection applied, and _Branches_ which takes a list of branch names, and defaults to the format used by the Generator. More details can be found with +```shell +SignalOnlyFitter.exe --help ``` For example, the fitter can be used to fit a toy MC sample generated by the generator by running: -``` -Generator MyOpts.opt --nEvents 100000 -SignalOnlyFitter MyOpts.opt --DataSample Generate_Output.root +```shell +AmpGen.exe MyOpts.opt --nEvents 100000 +SignalOnlyFitter.exe MyOpts.opt --DataSample Generate_Output.root ``` ## Advanced -This section contains miscellaneous details on more advanced functionality, including using python bindings and alternative parameterisation of the spin factors. +This section contains miscellaneous details on more advanced functionality, including using python bindings and alternative parameterisations of the spin factors. ### Table of contents * [Python Bindings](#python-bindings) @@ -244,7 +305,7 @@ This section contains miscellaneous details on more advanced functionality, incl ### Python Bindings Models built into a shared library can be used in python using the following flags into ConvertToSourceCode: ```shell -./ConvertToSourceCode MyOpts.opt --Output=MyFile.cpp --OutputEvents=events.csv --IncludePythonBindings +./AmpGen.exe MyOpts.opt --Output=MyFile.cpp --SourceOnly --OutputEvents=events.csv --IncludePythonBindings ``` where normalisation events are also output for testing purposes in events.csv. This can then be used with the python bindings in ampgen.py: @@ -262,7 +323,7 @@ fcn2 = data.apply(model.FCN, axis=1) ``` ### Particle Properties and Lineshape parameters -The particles available and their default properties can be found in *options/mass\_width.csv* using the MC format of the 2008 PDG. Additional pseudoparticles, such as nonresonant states and terms for use in conjunction with K-matrices are defined by *options/MintDalitzSpecialParticles.csv*. Any additional user defined particles should be added here. For the default lineshape (the relavistic Breit-Wigner or BW), there are three parameters: The mass, the width and the Blatt-Weisskopf radius. These default to their PDG values, but can be overridden in the options file with parameters: *particleName*\_mass, *particleName*\_width, *particleName*\_radius. To vary the mass of the @f$K_1(1270)^+@f$ meson, the line: +The particles available and their default properties can be found in *options/mass\_width.csv* using the MC format of the 2008 PDG. Additional pseudoparticles, such as nonresonant states and terms for use in conjunction with K-matrices are defined by *options/MintDalitzSpecialParticles.csv*. Any additional user defined particles should be added here. For the default lineshape (the relavistic Breit-Wigner or BW), there are three parameters: The mass, the width and the Blatt-Weisskopf radius. These default to their PDG values, but can be overridden in the options file with parameters: *particleName*\_mass, *particleName*\_width, *particleName*\_radius. To vary the mass of the $K_1(1270)^+$ meson, the line: ``` K(1)(1270)+_mass 0 1.270 0.01 ``` @@ -273,20 +334,20 @@ Other lineshapes may define other parameters, for example channel couplings or p Parameters can either be specified by three parameters, in the case of a scalar parameter such as a mass or a width, or with six parameters in the case of a complex parameter such as a coupling. Upper and lower bounds on parameters can also be set by specifying a parameter with five parameters or ten parameters for a scalar or complex, respectively. -For example, if we wished to vary the mass of the @f$K_1(1270)^+@f$ meson in the above example, but restricting the allowed values in the range @f$[0.0,2.0]\,\mathrm{GeV}@f$: +For example, if we wished to vary the mass of the $K_1(1270)^+$ meson in the above example, but restricting the allowed values in the range $[0.0,2.0]\,\mathrm{GeV}$: ``` K(1)(1270)+_mass 0 1.27 0.01 0.0 2.0 ``` Parameters can also be related to each other via expressions, -Suppose for example we have @f$K_1(1270)^+@f$ and @f$K_1(1270)^-@f$ in the same fit (for example, in @f$D^0 \to K^- K^+ \pi^- \pi^+@f$) -The properties of one can be allowed to vary, for example the @f$K_1(1270)^+@f$, and the other fixed to the same value, using: +Suppose for example we have $K_1(1270)^+$ and $K_1(1270)^-$ in the same fit (for example, in $D^0 \to K^- K^+ \pi^- \pi^+$) +The properties of one can be allowed to vary, for example the $K_1(1270)^+$, and the other fixed to the same value, using: ``` K(1)(1270)+_mass 0 1.27 0.01 0.0 2.0 K(1)(1270)bar-_mass = K(1)(1270)+_mass ``` Parameter expressions are whitespace delimited due to the abundance of **odd** glyphs such as brackets and +/- in the names of parameters. -Expressions support the binary operations @f$(+,-,/,* )@f$, as well as common unary functions such as sqrt, trigonometric functions etc. +Expressions support the binary operations $(+,-,/,* )$, as well as common unary functions such as sqrt, trigonometric functions etc. ### Spin Formalisms @@ -301,7 +362,7 @@ The spin formalism for an individual decay chain can be specified by changing th ``` D0[SpinFormalism=Canonical]{K*(892)bar0,rho(770)0} ``` -selects the S-wave of the @f$K^* \rho@f$ system. The user can also specify systems of helicity couplings in the canonical formalism, using the attribute _helAmp_. For example, suppose the transversity amplitudes were used rather than the canonical, then the user can specify +selects the S-wave of the $K^* \rho$ system. The user can also specify systems of helicity couplings in the canonical formalism, using the attribute _helAmp_. For example, suppose the transversity amplitudes were used rather than the canonical, then the user can specify ``` D0[SpinFormalism=Canonical;helAmp=Long]{K*(892)bar0,rho(770)0} D0[SpinFormalism=Canonical;helAmp=t1]{K*(892)bar0,rho(770)0} @@ -327,8 +388,9 @@ That is specified as sets of three numbers, firstly the coupling, and then the t ### Quasiparticles -Quasiparticles are (semi)fictional decaying particles that can be implemented in the decay chain for a variety of different purposes. The original use case was to group some amplitudes with the same quantum numbers with couplings that want to be factorised. -For example, for the @f$I=0@f$ @f$S@f$-wave, the K matrix description may be used. The coupling from the initial state may be written as +Quasiparticles are fictional decaying particles that can be implemented in the decay chain for a variety of different purposes. The original use case was to group some amplitudes with the same quantum numbers with couplings that want to be factorised. +For example, for the $I=0$ $S$-wave, the K matrix description may be used. The coupling from the initial state may be written as + ``` D0{K0S0,NonResS0} ... ``` @@ -337,7 +399,7 @@ The quasiparticle _NonResS0_ can then be decayed to the final state via the K ma NonResS0[kMatrix.pole.0]{pi+,pi-} ... NonResS0[kMatrix.pole.1]{pi+,pi-} ... ... -``` +``` where each of the .X is one of the terms of the (pole) production vector. In this example, an equivalent formulation would be ``` diff --git a/Standalone.cmake b/Standalone.cmake deleted file mode 100644 index 8784ca4f74f..00000000000 --- a/Standalone.cmake +++ /dev/null @@ -1,233 +0,0 @@ -set(AMPGEN_CXX ${CMAKE_CXX_COMPILER} CACHE FILEPATH "This should be the path to compiler (use which c++ for macOS)" ) - -file(TO_CMAKE_PATH "${PROJECT_BINARY_DIR}/CMakeLists.txt" LOC_PATH) -if(EXISTS "${LOC_PATH}") - message(FATAL_ERROR "You cannot build in a source directory (or any directory with a CMakeLists.txt file). Please make a build subdirectory. Feel free to remove CMakeCache.txt and CMakeFiles.") -endif() - -file(GLOB_RECURSE AMPGEN_SRC src/*) -file(GLOB_RECURSE AMPGEN_HDR AmpGen/*) - -if( NOT "${CMAKE_CXX_STANDARD}" ) - set(CMAKE_CXX_STANDARD 17) -endif() - -SET(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") # flag to use openmp for threading -SET(USE_SIMD "AVX2d" CACHE STRING "USE_SIMD") # AVX instruction set + precision to use -SET(USE_MVEC TRUE CACHE BOOL "USE_MVEC") # flag to use vector math library mvec - -set(CMAKE_CXX_EXTENSIONS OFF) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/bin") -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/bin") -set(CMAKE_TEST_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/test") - -include(CMakeDependentOption) -include(CMakePrintHelpers) -include(GNUInstallDirs) - -option(AMPGEN_DEBUG "AmpGen Debug printout") -option(AMPGEN_TRACE "AmpGen Trace printout") - - -configure_file ("${PROJECT_SOURCE_DIR}/AmpGen/Version.h.in" "${CMAKE_BINARY_DIR}/AmpGenVersion.h") - -add_library(${PROJECT_NAME} SHARED ${AMPGEN_SRC} ${AMPGEN_HDR}) -add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) - -if(DEFINED ENV{ROOTSYS}) - list(APPEND CMAKE_MODULE_PATH "$ENV{ROOTSYS}/etc/cmake/") -endif() - -find_package(ROOT CONFIG REQUIRED COMPONENTS Matrix MathMore MathCore Gpad Tree Graf) - -if( USE_OPENMP ) - find_package(OpenMP) -endif() - -cmake_print_variables(CMAKE_SOURCE_DIR) - -# Default build type from the Kitware Blog -set(default_build_type "Release") -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - message(STATUS "Setting build type to '${default_build_type}' as none was specified.") - set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE - STRING "Choose the type of build." FORCE) - # Set the possible values of build type for cmake-gui - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Release" "MinSizeRel" "RelWithDebInfo") -endif() - -target_include_directories(AmpGen PUBLIC $ - $ ) - -target_include_directories(AmpGen SYSTEM PUBLIC "${ROOT_INCLUDE_DIRS}") - -target_link_libraries(AmpGen PUBLIC -lm ${ROOT_LIBRARIES} ${CMAKE_DL_LIBS} ) - -find_library(libmvec mvec) - -if ( USE_MVEC AND libmvec ) - message( STATUS "Using libmvec for vectorised math operations") - target_link_libraries(AmpGen PUBLIC mvec) - target_compile_definitions(AmpGen PUBLIC "USE_MVEC=1") -else() - message( STATUS "Warning: libmvec not found, with use scalar math where necessary.") - target_compile_definitions(AmpGen PUBLIC "USE_MVEC=0") -endif() - - - -if( ( NOT TARGET ROOT::Minuit2 AND NOT TARGET Minuit2 ) OR "${extern_minuit2}" ) - message( STATUS "Use external Minuit2") - add_subdirectory("extern/Minuit2") - set_target_properties(Minuit2 PROPERTIES FOLDER extern) - target_compile_options(Minuit2 PUBLIC -fPIC -Wno-suggest-override) - set_target_properties(Minuit2Math PROPERTIES FOLDER extern) - add_library(ROOT::Minuit2 ALIAS Minuit2) - target_include_directories( AmpGen PUBLIC "${CMAKE_SOURCE_DIR}/extern/Minuit2/inc/") -else() - message( STATUS "Use ROOT::Minuit2") -endif() -if ( TARGET Minuit2 AND NOT TARGET ROOT::Minuit2 ) - find_package( ROOT CONFIG REQUIRED COMPONENTS Minuit2) - add_library(ROOT::Minuit2 ALIAS Minuit2) -endif() - -target_link_libraries(AmpGen PUBLIC ROOT::Minuit2 ) - -if( USE_OPENMP ) - target_compile_definitions(AmpGen PUBLIC "USE_OPENMP=1") - if(OpenMP_FOUND OR OpenMP_CXX_FOUND) - if(NOT TARGET OpenMP::OpenMP_CXX) - add_library(OpenMP::OpenMP_CXX IMPORTED INTERFACE) - set_property(TARGET OpenMP::OpenMP_CXX PROPERTY INTERFACE_COMPILE_OPTIONS ${OpenMP_CXX_FLAGS}) - set_property(TARGET OpenMP::OpenMP_CXX PROPERTY INTERFACE_LINK_LIBRARIES ${OpenMP_CXX_FLAGS}) - if(CMAKE_VERSION VERSION_LESS 3.4) - set_property(TARGET OpenMP::OpenMP_CXX APPEND PROPERTY INTERFACE_LINK_LIBRARIES -pthread) - else() - find_package(Threads REQUIRED) - set_property(TARGET OpenMP::OpenMP_CXX APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads) - endif() - endif() - target_link_libraries(AmpGen PUBLIC OpenMP::OpenMP_CXX) - else() - message(STATUS "OpenMP not found for CXX, you might have forgotten lb-run ROOT bash or CXX=`which g++` in CERN stack") - endif() -else() - target_compile_definitions(AmpGen PUBLIC "USE_OPENMP=0") -endif() - -set(RAPIDSIM_DATA "") - -if( "${USE_RAPIDSIM}" ) - include(${CMAKE_ROOT}/Modules/FetchContent.cmake) - FetchContent_Declare( RapidSim GIT_REPOSITORY https://github.com/gcowan/RapidSim/ ) - if(NOT RapidSim_POPULATED) - message("Fetching RapidSim from: https://github.com/gcowan/RapidSim/") - FetchContent_Populate(RapidSim) - endif() - FetchContent_GetProperties(RapidSim) - set(RAPIDSIM_DATA "${CMAKE_BINARY_DIR}/_deps/rapidsim-src/rootfiles/" ) -endif() - -if( RAPIDSIM_DATA ) - message("Set RAPIDSIM_DATA = ${RAPIDSIM_DATA}") -endif() - -# Default to XROOTD only if on CMT system. Can be overridden with -DAMPGEN_XROOTD=ON -if(DEFINED ENV{CMTCONFIG}) - set(AMPGEN_XROOTD_DEFAULT ON) -else() - set(AMPGEN_XROOTD_DEFAULT OFF) -endif() - -cmake_dependent_option(AMPGEN_XROOTD "Turn on XROOTD discovery" ON "AMPGEN_XROOTD_DEFAULT" OFF) - -if(AMPGEN_XROOTD) - find_library(XROOTD_LIB NAMES libXrdCl.so - HINTS "/cvmfs/lhcb.cern.ch/lib/lcg/releases/LCG_89/xrootd/4.6.0/$ENV{CMTCONFIG}/lib64") - target_link_libraries(AmpGen PUBLIC ${XROOTD_LIB}) -endif() - -target_compile_definitions(AmpGen PRIVATE - "AMPGENROOT_CMAKE=\"${CMAKE_BINARY_DIR}/bin\"" - "AMPGENROOT=\"${PROJECT_SOURCE_DIR}\"" - "AMPGEN_CXX=\"${AMPGEN_CXX}\"" - $<$:DEBUGLEVEL=1> - $<$:TRACELEVEL=1>) - - -target_compile_options(AmpGen - INTERFACE - -Wall -Wextra -Wpedantic -g3 - -Wno-unused-parameter - -Wno-unknown-pragmas - $<$:-O3>) - -if ( ${USE_SIMD} MATCHES "AVX2d" ) - message(STATUS "Enabling AVX2 [double precision]") - target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=1" "ENABLE_AVX2d=1") - target_compile_options(AmpGen PUBLIC -march=native -ftree-vectorize -mavx2 -ffast-math -DHAVE_AVX2_INSTRUCTIONS) -elseif ( ${USE_SIMD} MATCHES "AVX2f" ) - message(STATUS "Enabling AVX2 [single precision]") - target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=1" "ENABLE_AVX2f=1") - target_compile_options(AmpGen PUBLIC -march=native -ftree-vectorize -mavx2 -ffast-math -DHAVE_AVX2_INSTRUCTIONS) -elseif ( ${USE_SIMD} MATCHES "AVX512d" ) - message(STATUS "Enabling AVX2 [double precision]") - target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=1" "ENABLE_AVX512=1") - target_compile_options(AmpGen PUBLIC -march=native -ftree-vectorize -mavx512f -ffast-math -DHAVE_AVX512_INSTRUCTIONS) -else() - target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=0") - target_compile_options(AmpGen PUBLIC -march=x86-64) - message("SIMD disabled, resorting to scalar build : ${USE_SIMD}") -endif() - -if(${CMAKE_CXX_COMPILER_ID} MATCHES "AppleClang" OR - ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" ) - target_compile_options(AmpGen PUBLIC -mfma) -endif() - -if("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" ) - target_link_libraries(AmpGen PUBLIC stdc++ ) - message(STATUS "Using OSX specific flags: -lm -lstdc++ -lSystem") - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -lstdc++ -lSystem") -elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - target_link_libraries(AmpGen PUBLIC stdc++) - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lm -lstdc++") -else() - target_compile_options(AmpGen PUBLIC -Wno-suggest-override) -endif() - -file(GLOB_RECURSE applications apps/*.cpp examples/*.cpp ) - -foreach( file ${applications} ) - get_filename_component( Executable ${file} NAME_WE ) - # cmake_print_variables(Executable) - add_executable(${Executable} ${file}) - target_compile_options(${Executable} PUBLIC -g3 -Ofast) - target_link_libraries(${Executable} PUBLIC AmpGen ) -endforeach() - -file(GLOB_RECURSE options_files options/*.*) -execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/bin") -foreach(file ${options_files}) - get_filename_component(OptionFile "${file}" NAME) - # cmake_print_variables(OptionFile) - execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${file}" "${CMAKE_BINARY_DIR}/bin/${OptionFile}") -endforeach() - -enable_testing() -set(Boost_NO_BOOST_CMAKE ON) -add_subdirectory(test) - -include(CMakePackageConfigHelpers) -write_basic_package_version_file(AmpGenVersion.cmake VERSION ${PACKAGE_VERSION} COMPATIBILITY AnyNewerVersion) -configure_file(AmpGenConfig.cmake.in AmpGenConfig.cmake) - -export( TARGETS AmpGen NAMESPACE AmpGen:: FILE AmpGenTargets.cmake ) -set(CMAKE_EXPORT_PACKAGE_REGISTRY ON) -export(PACKAGE AmpGen) diff --git a/apps/Generator.cpp b/apps/AmpGen.cpp similarity index 82% rename from apps/Generator.cpp rename to apps/AmpGen.cpp index 72652742fc0..4beaba2169c 100644 --- a/apps/Generator.cpp +++ b/apps/AmpGen.cpp @@ -69,6 +69,46 @@ struct FixedLibPDF void reset( const bool& flag = false ){}; }; +template void generateSource(T& pdf, const std::string& sourceFile, MinuitParameterSet& mps) +{ + bool normalise = NamedParameter("Normalise",true); + double safetyFactor = NamedParameter( "SafetyFactor", 3 ); + int seed = NamedParameter("Seed", 1); + size_t nEvents = NamedParameter( "NormEvents", 1000000 ); + + TRandom3 rnd(seed); + + Generator phsp(pdf.eventType()); + phsp.setRandom(&rnd); + EventList normEvents = phsp.generate(nEvents); + if constexpr( std::is_same::value ) pdf.prepare(); + + double norm = 1; + if( normalise ){ + double pMax = 0; + for ( auto& evt : normEvents ) + { + if constexpr ( std::is_same::value ) + { + double px, py, pz; + rnd.Sphere(px,py,pz, rnd.Uniform(0,1)); + mps["Px"]->setCurrentFitVal(px); + mps["Py"]->setCurrentFitVal(py); + mps["Pz"]->setCurrentFitVal(pz); + pdf.transferParameters(); + } + double n = 0; + if constexpr ( std::is_same::value ) n = std::norm( pdf.getValNoCache(evt) ); + if constexpr ( std::is_same::value ) n = pdf.getValNoCache(evt); + if ( n > pMax ) pMax = n; + } + norm = pMax * safetyFactor ; + INFO( "Making binary with " << pMax << " x safety factor = " << safetyFactor ); + } + mps.resetToInit(); + pdf.generateSourceCode( sourceFile, norm, true ); +} + template Particle getTopology(const pdf_t& pdf) { @@ -92,6 +132,7 @@ template std::vector getDecayChains( const pdf_t& pdf } } + template void generateEvents( EventList& events , pdf_t& pdf , const phspTypes& phsp_type @@ -155,7 +196,7 @@ int main( int argc, char** argv ) , std::make_pair(phspTypes::RecursivePhaseSpace, "Includes possible quasi-stable particles and the phase spaces of their decay products, such as Λ baryons.\0") ) ); std::string lib = NamedParameter("Library","","Name of library to use for a fixed library generation"); size_t nBins = NamedParameter ("nBins" ,100, "Number of bins for monitoring plots." ); - + bool sourceOnly = NamedParameter ("SourceOnly",false, "Flag to only generate the source code, but not produce any events"); #ifdef _OPENMP unsigned int concurentThreadsSupported = std::thread::hardware_concurrency(); unsigned int nCores = NamedParameter( "nCores", concurentThreadsSupported, "Number of cores to use (OpenMP only)" ); @@ -193,6 +234,20 @@ int main( int argc, char** argv ) INFO("Using: " << nCores << " / " << concurentThreadsSupported << " threads" ); #endif + if( sourceOnly ) + { + if ( pdfType == pdfTypes::CoherentSum ) + { + CoherentSum pdf( eventType, MPS); + generateSource(pdf, outfile, MPS); + } + else if ( pdfType == pdfTypes::PolarisedSum ) + { + PolarisedSum pdf(eventType, MPS); + generateSource(pdf, outfile, MPS); + } + return 0; + } INFO("Generating time-dependence? " << eventType.isTimeDependent() ); EventList accepted( eventType ); diff --git a/apps/ConvertToSourceCode.cpp b/apps/ConvertToSourceCode.cpp deleted file mode 100644 index 43b77c0048c..00000000000 --- a/apps/ConvertToSourceCode.cpp +++ /dev/null @@ -1,149 +0,0 @@ -#include -#include -#include -#include - -#include "AmpGen/EventList.h" -#include "AmpGen/EventType.h" -#include "AmpGen/CoherentSum.h" -#include "AmpGen/PolarisedSum.h" -#include "AmpGen/Generator.h" -#include "AmpGen/MinuitParameterSet.h" -#include "AmpGen/NamedParameter.h" -#include "AmpGen/PhaseSpace.h" -#include "AmpGen/Utilities.h" -#include "AmpGen/ThreadPool.h" -#include "AmpGen/Particle.h" -#include "AmpGen/ParticlePropertiesList.h" -#include "AmpGen/AddCPConjugate.h" -#include "AmpGen/simd/utils.h" -#include "TRandom3.h" - -using namespace AmpGen; - -/* -template -void create_integration_tests(T& pdf, - const EventType& type, - const MinuitParameterSet& mps, - const std::vector& testEvents, - const std::string& sourceFile) -{ - auto stringify = [](const std::string arg ){ return "\"" + arg + "\"" ; }; - std::ofstream unit_tests; - unit_tests.open(split( sourceFile, '.')[0] + "_test.cpp"); - unit_tests << "#define BOOST_TEST_DYN_LINK" << std::endl; - unit_tests << "#define BOOST_TEST_MODULE amp" << std::endl; - unit_tests << "#include " << std::endl; - unit_tests << "#include \"AmpGen/Particle.h\"" << std::endl; - unit_tests << "#include \"AmpGen/CompiledExpression.h\"" << std::endl; - unit_tests << "#include \"AmpGen/EventType.h\"" << std::endl; - unit_tests << "#include \"AmpGen/MinuitParameterSet.h\"" << std::endl; - unit_tests << "#include \"AmpGen/OptionsParser.h\"" << std::endl; - unit_tests << "using namespace AmpGen;" << std::endl; - - unit_tests << "void setupOptions(){" << std::endl; - for( auto& p : *OptionsParser::getMe() ) - { - unit_tests << " OptionsParser::setArg( \"" << vectorToString(p.second," ") <<"\");"<< std::endl; - } - unit_tests << "\n}\n" << std::endl; - - for( auto& mE : pdf.matrixElements() ){ - auto value = mE.amp(testEvents[0].address()); - unit_tests << "BOOST_AUTO_TEST_CASE( " << mE.amp.progName() + "_test){" << std::endl; - unit_tests << " EventType type({" << stringify(type.mother()) << ", " << vectorToString( type.finalStates(), ", ", stringify ) << "});" << std::endl; - unit_tests << " Particle p("<(p.getExpression(), p.decayDescriptor(), type.getEventFormat(), mps);" << std::endl; - unit_tests << " auto eval = expr(event);" << std::endl; - unit_tests << " BOOST_TEST( std::real(eval) == " << std::real(utils::get<0>(value))<< ", boost::test_tools::tolerance(1e-6)) ;" << std::endl; - unit_tests << " BOOST_TEST( std::imag(eval) == " << std::imag(utils::get<0>(value))<< ", boost::test_tools::tolerance(1e-6)) ;" << std::endl; - unit_tests << "}\n\n"; - } - unit_tests.close(); -} -*/ - -template void generate_source(T& pdf, const std::string& sourceFile, MinuitParameterSet& mps, const double& sf) -{ - bool normalise = NamedParameter("Normalise",true); - double safetyFactor = NamedParameter( "SafetyFactor", 3 ); - int seed = NamedParameter("Seed", 1); - size_t nEvents = NamedParameter( "NormEvents", 1000000 ); - auto oEventType = NamedParameter("EventType").getVector(); - - TRandom3 rnd(seed); - - EventType eventType( oEventType ); - Generator phsp(eventType); - phsp.setRandom(&rnd); - EventList normEvents = phsp.generate(nEvents); - if constexpr( std::is_same::value ) pdf.prepare(); - - double norm = 1; - if( normalise ){ - double pMax = 0; - for ( auto& evt : normEvents ) - { - if constexpr ( std::is_same::value ) - { - double px, py, pz; - rnd.Sphere(px,py,pz, rnd.Uniform(0,1)); - mps["Px"]->setCurrentFitVal(px); - mps["Py"]->setCurrentFitVal(py); - mps["Pz"]->setCurrentFitVal(pz); - pdf.transferParameters(); - } - double n = 0; - if constexpr ( std::is_same::value ) n = std::norm( pdf.getValNoCache(evt) ); - if constexpr ( std::is_same::value ) n = pdf.getValNoCache(evt); - if ( n > pMax ) pMax = n; - } - norm = pMax * sf ; - INFO( "Making binary with " << pMax << " x safety factor = " << sf ); - } - mps.resetToInit(); - pdf.generateSourceCode( sourceFile, norm, true ); -} - -int main( int argc, char** argv ) -{ - OptionsParser::setArgs( argc, argv ); - std::vector oEventType = NamedParameter( "EventType" ).getVector(); - std::string sourceFile = NamedParameter( "Output" , "output.cpp" ); - std::string type = NamedParameter( "Type", "CoherentSum" ); - std::string outputPS = NamedParameter( "OutputEvents", "" ); - unsigned int NormEvents = NamedParameter( "NormEvents", 1000000 ); - double safetyFactor = NamedParameter( "SafefyFactor", 3 ); - unsigned seed = NamedParameter("Seed", 0); - EventType eventType( oEventType ); - - AmpGen::MinuitParameterSet MPS; // - MPS.loadFromStream(); - - if ( NamedParameter( "conj", false ) == true ) { - eventType = eventType.conj(true); - AddCPConjugate(MPS); - } - Generator phsp( eventType ); - TRandom3 rnd; - rnd.SetSeed( seed ); - gRandom = &rnd; - phsp.setRandom( &rnd ); - - if( type == "CoherentSum" ){ - CoherentSum sig( eventType, MPS, "" ); - generate_source( sig, sourceFile, MPS, safetyFactor ); - } - if( type == "PolarisedSum" ){ - PolarisedSum sig( eventType, MPS ); - generate_source( sig, sourceFile, MPS, safetyFactor ); - } -} diff --git a/apps/lib_diff.cpp b/apps/LibDiff.cpp similarity index 100% rename from apps/lib_diff.cpp rename to apps/LibDiff.cpp diff --git a/doc/figs/k3pi_s01.svg b/doc/figs/k3pi_s01.svg new file mode 100644 index 00000000000..8aa81f430ac --- /dev/null +++ b/doc/figs/k3pi_s01.svg @@ -0,0 +1,593 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/lb2jspiL_s01.svg b/doc/figs/lb2jspiL_s01.svg new file mode 100644 index 00000000000..6e9f53f0acd --- /dev/null +++ b/doc/figs/lb2jspiL_s01.svg @@ -0,0 +1,544 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/lb2jspiL_s012.svg b/doc/figs/lb2jspiL_s012.svg new file mode 100644 index 00000000000..d0c6dcf3164 --- /dev/null +++ b/doc/figs/lb2jspiL_s012.svg @@ -0,0 +1,555 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/lb2pKpi_s01.svg b/doc/figs/lb2pKpi_s01.svg new file mode 100644 index 00000000000..dfd139bd86e --- /dev/null +++ b/doc/figs/lb2pKpi_s01.svg @@ -0,0 +1,594 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/lb2pKpi_s02.svg b/doc/figs/lb2pKpi_s02.svg new file mode 100644 index 00000000000..d8c6194511e --- /dev/null +++ b/doc/figs/lb2pKpi_s02.svg @@ -0,0 +1,713 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/lb2pKpi_s12.svg b/doc/figs/lb2pKpi_s12.svg new file mode 100644 index 00000000000..364f6647442 --- /dev/null +++ b/doc/figs/lb2pKpi_s12.svg @@ -0,0 +1,715 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/s12.svg b/doc/figs/s12.svg new file mode 100644 index 00000000000..364f6647442 --- /dev/null +++ b/doc/figs/s12.svg @@ -0,0 +1,715 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig0.png b/doc/figs/tex/fig0.png deleted file mode 100644 index d13cb4c9611a607e36a7e50b6284728c454cd108..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 688 zcmeAS@N?(olHy`uVBq!ia0vp^5kM@)0wfrg#Jv0pq?nSt-CY>?t&Hpz19_YU9+AaB zx&n;nevL{1GT2KzeO=ifvxzZCD1G#Oeu;sBalfaFV~EE2-plqLcLHP%d{lV4M0Dlk zxl!t|Iy<`f^sejW7K+5U=!UhwTFCC7!QajotF_B>`n<{AhdaCTwsVwquc(OiTHx#` zBjWE@9QWz%dsThItf*hg|9?C^{Ql|Rd)-I>A5)FkZoF>pp>=-AZ?r`Wyx%P(1 zvu-44EEG>xJg`~O?eShEY1hczSBsc-SN*#xbZ_y4*~xp} z6x>txPxsuj$o=kQALBh937MO3Clzcz*sG-XVq@C^@nuSPG>uP6$ZXAX*VLRg`Hb2< zX|CA#&BB# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig1.png b/doc/figs/tex/fig1.png deleted file mode 100644 index d2628271c67f48f523272d4b64f9868dd803d4ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 744 zcmeAS@N?(olHy`uVBq!ia0vp^F+eQN0wfsHUeD43QcOwS?k)`cRz`M-{(zeXhh8SEvVzOL+#*~Azmls@`Czr?`6_}$aRF~s8Z)XC?wuQ-Stcb@39@@V~n z3zM6+%-B6WE+}f%jK#;3G#7cCmE&Sw`c}^6sPoN7t^$g-rTT~7Xl?BK{r|vk(Kna1i;ldq7LevB(P2n6E^SN&HzFz@TD zFwB9xozr$ja(rOy$m06*Yj*|n|JZ@ zMvslD52Dw7o3PA`Z7L)G+^H8$8#GT9wkK`Bus-$UE30!y+w{$Ei|w*1;D28?dr2LS zbY!~C<*hN@>vziCcf8x=-)8UlWv0AMp~=Lf@rUBGxEZGiu?zg*ZSXuX`=;Dfz;bBoe4 zJKkHoSfP2(@FSC~Ug>l>+e7D1mjB}PS9RRh{#f&#$z#dPl+J?rO0}Z)D{d{>n>UGl zvF5*Tf9L6jPRlv8{_>Nnn(oV4HkfVdj6d~Cp#IEmgGar!ht57(wa9$Ro^+8r46NJ# zZ;QyQ@Dr3f8UO8b(39+oe}kAZgEF2epXdH)Vfp#-)6?M*zw3MLpTA#yy1mJBKQL9O zmbgZgq$HN4S|t~y0x1R~14Bz)12bJC!w@4QD diff --git a/doc/figs/tex/fig1.svg b/doc/figs/tex/fig1.svg new file mode 100644 index 00000000000..6f3f59ddf13 --- /dev/null +++ b/doc/figs/tex/fig1.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig10.png b/doc/figs/tex/fig10.png deleted file mode 100644 index d4547c8fc76f4bf002ce7b8d17fad1c2ee7e5aa3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 716 zcmeAS@N?(olHy`uVBq!ia0vp^i-1^&1xPShEZ)8uNHHaOySp&(TN&9c2J$!yJR*yM zbOjjC{Th`3WU!Zb`ns||W)owO&=8!#cZPw1@wTUnV~EA+wIR0N%#H%QN=+Ucwrnu# zO{!~*ShiuqmcRh%jRJxG#}=G4ZJMgmlu)UevqmXm$%YF~NBlMh9DL;BsNEZPF2-(; z^mD!4)z#A_MCPPDfBRxr}~{>gsqjjGk{j_MMAUk7Og z#>|OkDmNcR2QYLUvG9K2c-!4rzvJEx=Z)Mif&O?dvG`$Zt;=E!rRR4#6K(b13T)6_ zeD|$UUwE*meNfU9k=ql@eq2ahbGfzAmFvl>Mb`trU(>qxI;cOA@9K-Yzb(nV^WM9FwH4DpNc6f&Evw}1mo77T zshBK~{^u3j!rp0zPp@43>(Ty0+Fs{hKCa-liI(~-aFlQ98|M!T^rS*AbJ;D{cF(rB zvc*!(UAA|}l5+}kR&gBjuRWb!@^puA)g{x=7wc~cPgu7Ww+c`Bxglugp{ac$_gut&?vNAHU zGBMCLFtRc*IGeLG4Mjt4eoAIqC2kFS3>j|$HHd(0C`d`O3QH|2&dkqa2yk)JHPkaz UV2$Cn1j;jby85}Sb4q9e0J$L{_W%F@ diff --git a/doc/figs/tex/fig10.svg b/doc/figs/tex/fig10.svg new file mode 100644 index 00000000000..b3c7c57fb17 --- /dev/null +++ b/doc/figs/tex/fig10.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig11.png b/doc/figs/tex/fig11.png deleted file mode 100644 index 38e8d29d6a2008bb4467fbc614b0e8754617b707..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 688 zcmeAS@N?(olHy`uVBq!ia0vp^5kM@)0wfrg#Jv0pq?nSt-CY>?t&Hpz19_YU9+AaB zx&n;nevL{1GT2KzeO=ifvxzZCXr|4#i(+74-0$h)7@~2$_p-gmodB5w9~GW15nVZX zZj^eg&W7?Hpy@D=K2W7C1Y~ zi1_;z$9;PHURB>PE9#f>{~u2ezkmAoUiZ=e$5bP>8?T#tXq{j38?DeZZ%fCzXurQD zO4H{%E_?Xk{GE_{5e-?26_5KJQUkKi_TPT8>1NK#e~D)kU$g1o{?YxgVXM*Z`7HGh zKWXN-hs>*$Vvey035nA@nEc^x&0T#hX74k``Wv1$3&oQa4{TO+d%Rak+BI_b)gq?dRsXIE-CO)%cJiJ# z1^1Nw(>?bra=$y-$9RuNLgwb%Nd?;v_A2SU*x0r}e3{Z6P2-aiGF$W9H8rPAKBIQe zxFWY;-^v3MzuFy{ztnm0Th?1T-rF6Q)tJ_1w0Aodb!XKSWM|90KHZ<+a=MoPw3}D= ztYY@vmN$*>d1&2xn)g&;-?B$9OJe^2&M%e!Z~c$q*6YyMT}*uJz}QtSag8WRNi0dV zN-jzTQVd20hL*YpX1Yd(Ax1`4MkZD!hS~;3Rt5&y(wi=!Xvob^$xN%ntwG9-D-Wna q1Y|=&N}5$zYEf}!ejY=Bi<_>Yo~Z(B47Vjvp25@A&t;ucLK6TI!Wo$W diff --git a/doc/figs/tex/fig11.svg b/doc/figs/tex/fig11.svg new file mode 100644 index 00000000000..430714dc97d --- /dev/null +++ b/doc/figs/tex/fig11.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig12.png b/doc/figs/tex/fig12.png deleted file mode 100644 index 00e1cad19b3bf511d5c10b588266a77f890143ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 565 zcmeAS@N?(olHy`uVBq!ia0vp^Q9vxl0wfp~th77?t&Hpz19_YU9+AaB zx&n;nevL{1GT2KzeO=ifvxzZCX#Jm-|A2vk(Z$onF+}5h@(+KmgdhLw`Rsnq=17zG z`1-!CX4PteGwBLf{XgEy?N9i(j(ycRHskBb;eVFPbw2(*|KWVQ8BhCTzkdJhF(>uE zWZkvL!GBqgRj?nC|8HCq+wcFiNMf z58Ypyt{?UPf3CP$ZrZ+Q~ zIPBlozN+q>75_S^<=zQ~--C-wAJ-6Urv1Z|NPGa(Gx$Jj;v!etUKVcZ!i1PEv6Qm zoou-H=Unz+WcdDOfzP39SCxT5tXkq4QIe8al4_M)lnSI6j0_Adbq&mPjSNGKjI4}I ztW1ow4UDV|45B`-@JG>*o1c=IR*74K_Bw&jKn)@w8wyg=tin=@iZk=`7y?|}bPe@P U6zopr08Fy$egFUf diff --git a/doc/figs/tex/fig12.svg b/doc/figs/tex/fig12.svg new file mode 100644 index 00000000000..9c2658ab34c --- /dev/null +++ b/doc/figs/tex/fig12.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig13.png b/doc/figs/tex/fig13.png deleted file mode 100644 index 3bcb1cc7a9489019aa7dfe371eed04e434ad9450..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 450 zcmeAS@N?(olHy`uVBq!ia0vp^%0Mi{0wfp=Q?B*^DW)WEcNYeJD(j(p$n@ z8uc$+kiMcE;_UbEl1Qtw3D>0?Mcbu58{R6(DqS5IxItx4efaLMC;Z=we(239)??hp z=#uT=KCgk{G^2UrzpNh%H4DU^u67wlv&Hfr(D}`%IkQ+k=ht8uPLi1*&7!o ziQR13kscP9(*3(bpv>^&(hqEp7!Rgyn7PEo)kG~q&M7o#&Ec&Y(b_A$xg^b!l7hEr z{My~~ohd5h+Kvl>^b(W9OyaK z64!{5l*E!$tK_0oAjM#0U}&jpV5Vzi7-D2(Wn^MyVx(5CPdxkdkHbP0l+XkKV2YtV diff --git a/doc/figs/tex/fig13.svg b/doc/figs/tex/fig13.svg new file mode 100644 index 00000000000..4772cdbc29a --- /dev/null +++ b/doc/figs/tex/fig13.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig14.png b/doc/figs/tex/fig14.png deleted file mode 100644 index aa02a85116eef75c96d810c6b1a8277054cf06a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 342 zcmeAS@N?(olHy`uVBq!ia0vp^B0$W~0wfq%m}5JD6jPG7y9)!qm66?IAdj=aBeEDs zSAg-{uTcp=278I8uPggwHZcYX?T(4@Wk8`+PZ!4!j_b0gHu5$xFtA>{Kl21b*}24w zj47fr2m1sxZXUhF7<1%E#D$G*f+sxJRqlMmbh@SG{)ZVVdm^2OC7#SE^>Kd5o8X1Nd8Ce;bSeY1W8yHy`82o8j{2N6>ZhlH;S|x4`y*H)Zff__W pHWZ|!S%sw*6=&w>F$B1{=^E;pDzL_ITLR@7JYD@<);T3K0RT0}X{Z1I diff --git a/doc/figs/tex/fig14.svg b/doc/figs/tex/fig14.svg new file mode 100644 index 00000000000..53f2dc72ac6 --- /dev/null +++ b/doc/figs/tex/fig14.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig15.svg b/doc/figs/tex/fig15.svg new file mode 100644 index 00000000000..d107ae8333f --- /dev/null +++ b/doc/figs/tex/fig15.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig16.svg b/doc/figs/tex/fig16.svg new file mode 100644 index 00000000000..30e7319ca92 --- /dev/null +++ b/doc/figs/tex/fig16.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig17.svg b/doc/figs/tex/fig17.svg new file mode 100644 index 00000000000..e06cb3fea26 --- /dev/null +++ b/doc/figs/tex/fig17.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig18.svg b/doc/figs/tex/fig18.svg new file mode 100644 index 00000000000..2c2621e562f --- /dev/null +++ b/doc/figs/tex/fig18.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig19.svg b/doc/figs/tex/fig19.svg new file mode 100644 index 00000000000..c4756c76dc2 --- /dev/null +++ b/doc/figs/tex/fig19.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig2.png b/doc/figs/tex/fig2.png deleted file mode 100644 index 17fa75658034301fc889fdeb11d4c8d21e413079..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 404 zcmeAS@N?(olHy`uVBq!ia0vp^;y^6K0wfp$YQCQXQcOwS?k)`cRz`M-{(zeXhh8SEvVzOL+#*~Azml-s_;l6_#35oSC1;5a8mbYp7?cz#7AC36y8>boFyt=akR{ E0JaR3s{jB1 diff --git a/doc/figs/tex/fig2.svg b/doc/figs/tex/fig2.svg new file mode 100644 index 00000000000..1d0aad29aeb --- /dev/null +++ b/doc/figs/tex/fig2.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig20.svg b/doc/figs/tex/fig20.svg new file mode 100644 index 00000000000..1bc66dad39a --- /dev/null +++ b/doc/figs/tex/fig20.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig21.svg b/doc/figs/tex/fig21.svg new file mode 100644 index 00000000000..9d2d8902ad9 --- /dev/null +++ b/doc/figs/tex/fig21.svg @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig22.svg b/doc/figs/tex/fig22.svg new file mode 100644 index 00000000000..7d96049e8cc --- /dev/null +++ b/doc/figs/tex/fig22.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig23.svg b/doc/figs/tex/fig23.svg new file mode 100644 index 00000000000..64b0735b240 --- /dev/null +++ b/doc/figs/tex/fig23.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig24.svg b/doc/figs/tex/fig24.svg new file mode 100644 index 00000000000..203e006c887 --- /dev/null +++ b/doc/figs/tex/fig24.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig25.svg b/doc/figs/tex/fig25.svg new file mode 100644 index 00000000000..1d0aad29aeb --- /dev/null +++ b/doc/figs/tex/fig25.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig26.svg b/doc/figs/tex/fig26.svg new file mode 100644 index 00000000000..7d652ec63a2 --- /dev/null +++ b/doc/figs/tex/fig26.svg @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig27.svg b/doc/figs/tex/fig27.svg new file mode 100644 index 00000000000..219c86f4c1a --- /dev/null +++ b/doc/figs/tex/fig27.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig28.svg b/doc/figs/tex/fig28.svg new file mode 100644 index 00000000000..203e006c887 --- /dev/null +++ b/doc/figs/tex/fig28.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig29.svg b/doc/figs/tex/fig29.svg new file mode 100644 index 00000000000..c1b4811dcda --- /dev/null +++ b/doc/figs/tex/fig29.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig3.png b/doc/figs/tex/fig3.png deleted file mode 100644 index 5d646ca2dc6eca90047c63d7e7e7e735b4fe34f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmeAS@N?(olHy`uVBq!ia0vp^(m*W40wfr`9K;=f6jPG7y9)!qm66?IAdj=aBeEDs zSAg-{uTcp=278I8uPggwHZcYX6$w43=Rl#Qo-U3d5|@*I@U!pV{k%TGpA(Fq`zQaS8B_N& z?0gAS`1jiX_k2&g{{MgfE&knpzA2~w{@;K4|I^#goppbp!`2Syb!j9Sh{!eW#*stDo_22)A + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig30.svg b/doc/figs/tex/fig30.svg new file mode 100644 index 00000000000..fae269e3c3d --- /dev/null +++ b/doc/figs/tex/fig30.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig31.svg b/doc/figs/tex/fig31.svg new file mode 100644 index 00000000000..1bc66dad39a --- /dev/null +++ b/doc/figs/tex/fig31.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig32.svg b/doc/figs/tex/fig32.svg new file mode 100644 index 00000000000..e7d8901dec9 --- /dev/null +++ b/doc/figs/tex/fig32.svg @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig33.svg b/doc/figs/tex/fig33.svg new file mode 100644 index 00000000000..237a622257f --- /dev/null +++ b/doc/figs/tex/fig33.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig34.svg b/doc/figs/tex/fig34.svg new file mode 100644 index 00000000000..cd6a77bec58 --- /dev/null +++ b/doc/figs/tex/fig34.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig35.svg b/doc/figs/tex/fig35.svg new file mode 100644 index 00000000000..cd6a77bec58 --- /dev/null +++ b/doc/figs/tex/fig35.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig36.svg b/doc/figs/tex/fig36.svg new file mode 100644 index 00000000000..b3116a75348 --- /dev/null +++ b/doc/figs/tex/fig36.svg @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig37.svg b/doc/figs/tex/fig37.svg new file mode 100644 index 00000000000..cd6a77bec58 --- /dev/null +++ b/doc/figs/tex/fig37.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig38.svg b/doc/figs/tex/fig38.svg new file mode 100644 index 00000000000..60c45e30ba3 --- /dev/null +++ b/doc/figs/tex/fig38.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig39.svg b/doc/figs/tex/fig39.svg new file mode 100644 index 00000000000..2b237e03225 --- /dev/null +++ b/doc/figs/tex/fig39.svg @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig4.png b/doc/figs/tex/fig4.png deleted file mode 100644 index 0973a8b9b63a88884d4b5c398aaa476cef6c4632..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 708 zcmeAS@N?(olHy`uVBq!ia0vp^vw>KM1xPTgag}ofQcOwS?k)`cRz`M-{(zeXhh8SEvVzOL+#*~AzmR3!AAo-;5oUiNfx46!)9HpJFjIZ%XGsY&PHr9)A( zML%;NF=}mH+S|0dH=<)lUrcjaymEwROvDD6?%Zub8$1#hwsypdaVzIcbamABHS6n} zJVWOFnLYexqZ6C&J)2jq_kPcB)5#56o_z}6b5o16b>YlhvqEp>n3loA0h(`bUc#tL`j}(OF)g zQ$9aw|I>YEs?^H9H@}XZmHni~W&4l2#vSb)%?CHel=l6d^6GY6&Tiq0D}M>jFL9Ut zFnd+5YKQiX8Bgm9lg`G8MlU|`%zd%&@v?bO|88ElJfQgV2E)^>+0Xg6^5jRYi{-pJ zB~e{|%bnOvUbD2F1#kCltyyQf@VefQgjv%+ZN0!`cf=^MyKXs zzlKjlL$7w{QNN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig40.svg b/doc/figs/tex/fig40.svg new file mode 100644 index 00000000000..cd6a77bec58 --- /dev/null +++ b/doc/figs/tex/fig40.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig41.svg b/doc/figs/tex/fig41.svg new file mode 100644 index 00000000000..f2a072cea11 --- /dev/null +++ b/doc/figs/tex/fig41.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig42.svg b/doc/figs/tex/fig42.svg new file mode 100644 index 00000000000..8be51763347 --- /dev/null +++ b/doc/figs/tex/fig42.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig43.svg b/doc/figs/tex/fig43.svg new file mode 100644 index 00000000000..f2c928f67e8 --- /dev/null +++ b/doc/figs/tex/fig43.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig44.svg b/doc/figs/tex/fig44.svg new file mode 100644 index 00000000000..c63d8cd345a --- /dev/null +++ b/doc/figs/tex/fig44.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig45.svg b/doc/figs/tex/fig45.svg new file mode 100644 index 00000000000..58c801d5579 --- /dev/null +++ b/doc/figs/tex/fig45.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig5.png b/doc/figs/tex/fig5.png deleted file mode 100644 index 13038b7527c48e065ba950f0d49a3bc480d96914..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 688 zcmeAS@N?(olHy`uVBq!ia0vp^5kM@)0wfrg#Jv0pq?nSt-CY>?t&Hpz19_YU9+AaB zx&n;nevL{1GT2KzeO=ifvxzZCsOD=H6*4d|?)P+Y4AD5>d)eOOPJqmTj|xwhh_0MG zH%dKLXGa&G-gUj)LXj93-LUpo3)%fM_}lqnwRU+{6&0~w3!EKg zMEw1V<37E8uc~jD74=K`|Bt7K-#`6(ulwl#W2zC`jn~aRw9YU2jaF!yx20oUwBO$n zrRnn>mpy!N{!Ylfh=wf1ipTv9sR3DM`)@zlbTen=zr?eNui5l(|LA_$u+?bye3tr$ zpEUE^L*~^=F~?Yhgv4ncO#X1U=B~b_KFj`t`DvVXpZI>QIDcg7?j3rPdy+md*WNIh zR>7pdQ2Ee3XU&A98xKlPw7id2;9mbIZ_B^D-h%xH1H@e$vv;07n9`DcUffu)PUi8d zEhpr83izg^*z}&?EqOI|{S8l>h2qJI2R19ZJ>IJ%?HalJY7x`!s()97?k#>WJ9*EW zf_uvT>7IKQx!;}aW4y;BA#?NXq=M}SdzJKFY;0Q~zD((krtwJ$nXP&5nwrxlpHaJK zT#;L_Z{>lBU+s>}U+TR0E$b~E@9mDuYD{Z0+Pj^Ky0dBuva{u0pYG3ZIbF+t+Rdwb zRx$f-%bUjcJhbjT&3me_Z`q@lB{Bbh=avibsE+#&9VC<@vxJHzuB$lLF zB^RXvDF!10LrYx)GhHLY5F;ZiBNHoQb8Q17D+2>2zP^tr8glbfGSez?YbXvj^95=U q0ohQHl4cc_T2!2wpT`j3;-+h;XR5#&!)*zaXYh3Ob6Mw<&;$UYP8o9m diff --git a/doc/figs/tex/fig5.svg b/doc/figs/tex/fig5.svg new file mode 100644 index 00000000000..285012c74e7 --- /dev/null +++ b/doc/figs/tex/fig5.svg @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig6.png b/doc/figs/tex/fig6.png deleted file mode 100644 index 18c7e5b04ad7e2a144bdc2c3514fd07a08e80528..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 688 zcmeAS@N?(olHy`uVBq!ia0vp^5kM@)0wfrg#Jv0pq?nSt-CY>?t&Hpz19_YU9+AaB zx&n;nevL{1GT2KzeO=ifvxzZCsC`pVKFz?uxZl&oF+}5h?`3+TEoAr4;BV)P)!OAbect5m!=2rE+d0a*S5(A$EpT>} z5%Kpcj{EfXy{f)pR@5)$|397{e*g6Ez3!v`kEup%H(odQ&^o{5H(H@--j^*20i7K$e;9@wnt_IR(7v}@${Zfxv9WD|_%fwCn#Lz3WVYtHYidrLd`9h_ zaYb&yzLf_ieziL?f2s50x2(5xytg|pt1+$3Xzz9^>dvYu$j+8~eY!ut<#a9oX*aL# zS;g$TEpHm%^U%8YH1DaxzGaVImc;!3onI>d-})cJt=FNiyO{Xcfw8Mv;u=wsl30>z zm0Xkxq!^403@vpH%yf+mLyU~9j7+SIEwl}ctPBjkxc!qr(U6;;l9^VCTSKd~+Y+D# q5s(c9DQQ+=sYS(^`FRWhE^fMpdZr4jG2E6wc?M5cKbLh*2~7Y#o*MxG diff --git a/doc/figs/tex/fig6.svg b/doc/figs/tex/fig6.svg new file mode 100644 index 00000000000..d996c971647 --- /dev/null +++ b/doc/figs/tex/fig6.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig7.png b/doc/figs/tex/fig7.png deleted file mode 100644 index e6e17b7a8f71304b710abaf145be98225632e4f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 761 zcmeAS@N?(olHy`uVBq!ia0vp^1wbsu0wfrITw8S!NHHaOySp&(TN&9c2J$!yJR*yM zbOjjC{Th`3WU!Zb`ns||W)owOQ2VB!d>W{U!_&nv#NzbaDfSs6jv~jlTc40+>DGvd z@LIFYN8qD?iJ8+H9u}3dm6J}-Pda!wN11aali00}jh{~OUiT16;no)1sUh|f9ChJduv)1XN%soyFTyEFLjSt{Q&v-TO#&2 z$9JTBc-$y_=H!dk&n>$f4sQA9cH-E*rcd`H_A@GT%;;l2w_?^8CypchsYmr+gnFLJ z-6I~oz4hq<4yJcM4y4C|4#|oJ*koV1VbjSzfyjE zl}DQN7L$2j^N&B&-uP^`%5vuLc2?F$Z@u3c@8rppm&y4UfB$0T_reXeGGcdr2OC7#SE^>Kd5o8X1Nd8Ce;bSQ%Sr z8yHy`7<_U2CxN0NH$NpatrE9}R%y2-Kn)@w8wyg=tin=@iZk=`7y?|}bPe@P6zopr0CC?sQvd(} diff --git a/doc/figs/tex/fig7.svg b/doc/figs/tex/fig7.svg new file mode 100644 index 00000000000..c5c6dacc2ec --- /dev/null +++ b/doc/figs/tex/fig7.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig8.png b/doc/figs/tex/fig8.png deleted file mode 100644 index 60ac3e54c3440050403923e9090f3fc7631881a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 688 zcmeAS@N?(olHy`uVBq!ia0vp^5kM@)0wfrg#Jv0pq?nSt-CY>?t&Hpz19_YU9+AaB zx&n;nevL{1GT2KzeO=ifvxzZCs5hz$$1*T5?)P+Y4AD5>d)eOOPJqmTj|xwhh_0MG zH%dKLXGa&G-gUj)LXj93-LUpo3)%fM_}lqnwRU+{6&0~w3!EKg zMEw1V<37E8uc~jD74=K`|Bt7K-#`6(ulwl#W2zC`jn~aRw9YU2jaF!yx20oUwBO$n zrRnn>mpy!N{!Ylfh=wf1ipTv9sR3DM`)@zlbTen=zr?eNui5l(|LA_$u+?bye3tr$ zpEUE^L*~^=F~?Yhgv4ncO#X1U=B~b_KFj`t`DvVXpZI>QIDcg7?j3rPdy+md*WNIh zR>7pdQ2Ee3XU&A98xKlPw7id2;9mbIZ_B^D-h%xH1H@e$vv;07n9`DcUffu)PUi8d zEhpr83izg^*z}&?EqOI|{S8l>h2qJI2R19ZJ>IJ%?HalJY7x`!s()97?k#>WJ9*EW zf_uvT>7IKQx!;}aW4y;BA#?NXq=M}SdzJKFY;0Q~zD((krtwJ$nXP&5nwrxlpHaJK zT#;L_Z{>lBU+s>}U+TR0E$b~E@9mDuYD{Z0+Pj^Ky0dBuva{u0pYG3ZIbF+t+Rdwb zRx$f-%bUjcJhbjT&3me_Z`q@lB{Bbh=avibsE+#&9VC<@vxJHzuB$lLF zB^RXvDF!10LrYx)GhHLY5F;ZiBNHoQOKk%qD+7Zd!>?;lH00)|WTsW()}Wl@D*)6W q0 + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/figs/tex/fig9.png b/doc/figs/tex/fig9.png deleted file mode 100644 index 51e926829469d613b6681e464a5487bcc004c5f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 675 zcmeAS@N?(olHy`uVBq!ia0vp^5kM@)0wfrg#Jv0pq?nSt-CY>?t&Hpz19_YU9+AaB zx&n;nevL{1GT2KzeO=ifvxzZCXb8^WJHx=hxXIJSF+}71)XVldDuFTwK6akqQd+*q z>FKP!PofrH(BWM)B}TcgAUvTtg+sd4$@zs#a_Du9Fq4wo9%1H(p2jFojw$SnDNIV8 zxz#v+zxll$#mOD<&(2rt&#yFo|Ghf-L!UuhnXLA)JOBANCeNzm^S%9E?&Qj-|4)iu z_J`!`dHH&{_GW7_g+A^oaMAzSNEj9T-KR4jo%gM z=pFg5d3$4pmfZCFKi1w8>=$Vd3;AoSHys$EswJ)wB`Jv|saDBFsX&Us$iUE2*T78I z$S}mn$jZpX%EUn1z{twL;B3y$G!zZF`6-!cmAEzRF=V_2)F1+~p&%vADlE0AI5R(w cA;85=*HF(?fi;HP5-88$>FVdQ&MBb@0M{T7AOHXW diff --git a/doc/figs/tex/fig9.svg b/doc/figs/tex/fig9.svg new file mode 100644 index 00000000000..1b49bbf978b --- /dev/null +++ b/doc/figs/tex/fig9.svg @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/release.notes b/doc/release.notes index cc2cb56fdc8..9d3af77ce0c 100644 --- a/doc/release.notes +++ b/doc/release.notes @@ -3,7 +3,10 @@ ! Responsible : Tim Evans ! Purpose : !----------------------------------------------------------------------------- -!=================== AmpGen v2r0 2020-25-04 +!=================== AmpGen v2r1 2020-28-10 ================== + - Improved cmake configuration to allow installation + - Consolidation of Generator and ConvertToSourceCode to single executable 'AmpGen' +!=================== AmpGen v2r0 2020-25-04 ================== - Refactored caching logic away from being computations being stored with event data. - Support for AVX2 for amplitude evaluation / integration single/double precision. - Updated plotting for making component amplitude plots. diff --git a/examples/fit_hyperon_parameters.cpp b/examples/FitHyperonParameters.cpp similarity index 100% rename from examples/fit_hyperon_parameters.cpp rename to examples/FitHyperonParameters.cpp diff --git a/src/ASTResolver.cpp b/src/ASTResolver.cpp index 8d761727546..b1366d6ba5e 100644 --- a/src/ASTResolver.cpp +++ b/src/ASTResolver.cpp @@ -80,7 +80,7 @@ template <> void ASTResolver::resolve( const Spline& spline ) addResolvedParameter( &spline, address ); addResolvedParameter( spline.m_points.top().get(), address ); auto splineTransfer = dynamic_cast( m_cacheFunctions[spline.m_name].get() ); - if( m_mps == nullptr ) ERROR("Fix me!"); + if( m_mps == nullptr ) ERROR("Fix me: Spline parameters must come from a ParameterSet"); for( unsigned int i = 0 ; i < spline.m_nKnots; ++i ) splineTransfer->set(i, m_mps->find(spline.m_name+"::"+std::to_string(i)) ); } diff --git a/src/CoherentSum.cpp b/src/CoherentSum.cpp index 378f50f2029..0465febdbf2 100644 --- a/src/CoherentSum.cpp +++ b/src/CoherentSum.cpp @@ -177,7 +177,7 @@ void CoherentSum::generateSourceCode(const std::string& fname, const double& nor auto expr = CompiledExpression( p.expression(), p.decayDescriptor(), - m_evtType.getEventFormat(), DebugSymbols() , m_mps ); + m_evtType.getEventFormat(), DebugSymbols(), disableBatch(), m_mps ); expr.prepare(); stream << expr << std::endl; expr.compileWithParameters( stream ); @@ -191,8 +191,8 @@ void CoherentSum::generateSourceCode(const std::string& fname, const double& nor Expression this_amplitude = p.coupling() * Function( programatic_name( p.name() ) + "_wParams", {event} ); amplitude = amplitude + ( p.decayTree.finalStateParity() == 1 ? 1 : pa ) * this_amplitude; } - stream << CompiledExpression(const double*, const int&)>( amplitude , "AMP" ) << std::endl; - stream << CompiledExpression(fcn::norm(amplitude) / normalisation, "FCN" ) << std::endl; + stream << CompiledExpression(const double*, const int&)>( amplitude , "AMP", disableBatch() ) << std::endl; + stream << CompiledExpression(fcn::norm(amplitude) / normalisation, "FCN", disableBatch() ) << std::endl; if( includePythonBindings ){ stream << CompiledExpression( m_matrixElements.size(), "matrix_elements_n" ) << std::endl; stream << CompiledExpression( normalisation, "normalization") << std::endl; diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 3c30970b31c..1dab616bbc8 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -353,7 +353,7 @@ void PolarisedSum::generateSourceCode(const std::string& fname, const double& no auto expr = CompiledExpression(const real_t*, const real_t*)>( p.expression(), p.decayDescriptor(), - m_eventType.getEventFormat(), DebugSymbols() ,m_mps ) ; + m_eventType.getEventFormat(), DebugSymbols(), m_mps, disableBatch() ) ; expr.prepare(); expr.to_stream( stream ); expr.compileWithParameters( stream ); diff --git a/src/Vertex.cpp b/src/Vertex.cpp index d96c0cd6955..4640697854c 100644 --- a/src/Vertex.cpp +++ b/src/Vertex.cpp @@ -13,14 +13,14 @@ using namespace AmpGen; -const Tensor::Index mu = Tensor::Index(); -const Tensor::Index nu = Tensor::Index(); -const Tensor::Index alpha = Tensor::Index(); -const Tensor::Index beta = Tensor::Index(); -const Tensor::Index a = Tensor::Index(); -const Tensor::Index b = Tensor::Index(); -const Tensor::Index c = Tensor::Index(); -const Tensor::Index d = Tensor::Index(); +static const Tensor::Index mu = Tensor::Index(); +static const Tensor::Index nu = Tensor::Index(); +static const Tensor::Index alpha = Tensor::Index(); +static const Tensor::Index beta = Tensor::Index(); +static const Tensor::Index a = Tensor::Index(); +static const Tensor::Index b = Tensor::Index(); +static const Tensor::Index c = Tensor::Index(); +static const Tensor::Index d = Tensor::Index(); template <> Factory* Factory::gImpl = nullptr; From 63a43fe04757587e374455a624095e4d0f05af0b Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 28 Oct 2020 22:41:05 +0100 Subject: [PATCH 237/250] fixes for CI --- AmpGen/CompiledExpression.h | 3 +++ CMakeLists.txt | 24 +++++++++++++----------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index 59ec81e4ccf..245c275ce09 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -65,6 +65,9 @@ namespace AmpGen }; for_each( std::tuple(args...), process_argument); DEBUG("Made expression: " << m_name << " " << progName() << " " << mps << " batch enabled ? " << this->m_enableBatch ); + #ifndef _OPENMP + this->m_enableBatch = false; + #endif resolve(mps); } diff --git a/CMakeLists.txt b/CMakeLists.txt index 2caa58580c7..6a6481af6ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ set(USE_SIMD "AVX2d" CACHE STRING "USE_SIMD") # AVX instruction set(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") # flag to use openmp for threading set(USE_MVEC TRUE CACHE BOOL "USE_MVEC") # flag to use vector math library mvec set(ENABLE_FITTING TRUE CACHE BOOL "ENABLE_FITTING") # flag to enable fitting (requires Minuit2) - +set(BUILTIN_GSL TRUE CACHE BOOL "BUILTIN_GSL") # flag to use ROOT's builtin GSL set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") @@ -48,18 +48,20 @@ if(NOT DEFINED ROOT_LIBRARIES) if(DEFINED ENV{ROOTSYS}) list(APPEND CMAKE_MODULE_PATH "$ENV{ROOTSYS}/etc/cmake/") endif() - find_package(ROOT CONFIG REQUIRED COMPONENTS Matrix MathMore MathCore Gpad Tree Graf) + find_package(ROOT COMPONENTS Matrix MathMore MathCore Gpad Tree Graf) else() string( REPLACE ":" " " ROOT_LIBRARIES ${ROOT_LIBRARIES}) separate_arguments(ROOT_LIBRARIES) endif() -# if( NOT DEFINED GSL_LIBRARIES ) -# find_package(GSL) -# else() -# string( REPLACE ":" " " GSL_LIBRARIES ${GSL_LIBRARIES}) -# separate_arguments(GSL_LIBRARIES) -# endif() +if( NOT BUILTIN_GSL ) + if( NOT DEFINED GSL_LIBRARIES ) + find_package(GSL) + else() + string( REPLACE ":" " " GSL_LIBRARIES ${GSL_LIBRARIES}) + separate_arguments(GSL_LIBRARIES) + endif() +endif() if( USE_OPENMP ) find_package(OpenMP) @@ -78,10 +80,9 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() -target_include_directories(AmpGen PUBLIC $ - $ ) +target_include_directories(AmpGen PUBLIC $ $ ) -target_include_directories(AmpGen SYSTEM PUBLIC "${ROOT_INCLUDE_DIRS}") +target_include_directories(AmpGen PUBLIC ${ROOT_INCLUDE_DIRS}) target_link_libraries(AmpGen PUBLIC -lm "${ROOT_LIBRARIES}" ${CMAKE_DL_LIBS} "${GSL_LIBRARIES}" ) @@ -217,6 +218,7 @@ foreach( file ${applications} ) add_executable(${Executable}.exe ${file}) target_compile_options(${Executable}.exe PUBLIC -g3 -Ofast) target_link_libraries(${Executable}.exe PUBLIC AmpGen ) + target_include_directories(${Executable}.exe PRIVATE ${ROOT_INCLUDE_DIRS}) endforeach() file(GLOB_RECURSE options_files options/*.*) From aba144e2c4cbad34cfb60797c57da9594773389e Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Wed, 28 Oct 2020 23:00:59 +0100 Subject: [PATCH 238/250] Remove export of includes from cmakelists to fix ROOT error --- CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a6481af6ae..414c9370bc6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,7 +82,8 @@ endif() target_include_directories(AmpGen PUBLIC $ $ ) -target_include_directories(AmpGen PUBLIC ${ROOT_INCLUDE_DIRS}) +# target_include_directories(AmpGen PUBLIC $ Date: Thu, 29 Oct 2020 08:49:30 +0100 Subject: [PATCH 239/250] yahh traviiss --- .ci/build_root.sh | 1 - .ci/travis_linux.sh | 2 +- .travis.yml | 11 ----------- CMakeLists.txt | 14 ++++++++++---- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/.ci/build_root.sh b/.ci/build_root.sh index 52c15b244d0..865eb1eec92 100755 --- a/.ci/build_root.sh +++ b/.ci/build_root.sh @@ -12,7 +12,6 @@ bash miniconda_${os}.sh -b -p $DEPS_DIR/miniconda export PATH="$DEPS_DIR/miniconda/bin:$PATH" hash -r conda config --add channels conda-forge -# conda config --set channel_priority strict conda create --yes -n env_${os} root doxygen -c conda-forge diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh index 93f735a9fe4..b3a17a80751 100755 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -9,7 +9,7 @@ conda activate env_${TRAVIS_OS_NAME} echo -en 'travis_fold:start:script.build\\r' echo "Building..." echo "Building under OS: $TRAVIS_OS_NAME, CXX =$CXX" - +echo "Directories: DEPS_DIR=$DEPS_DIR; TRAVIS_BUILD_DIR=$TRAVIS_BUILD_DIR" mkdir -p build.conda cd build.conda cmake .. diff --git a/.travis.yml b/.travis.yml index 24cbaaca55e..84c3110f45f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,17 +10,6 @@ matrix: packages: - libomp - os: linux - # addons: - # apt: - # sources: - # - ubuntu-toolchain-r-test - # packages: - # - g++-8 - # - doxygen - # - doxygen-doc - # - doxygen-gui - # - graphviz - # - libtbb-dev env: - MATRIX_EVAL="CC=gcc-8 && CXX=g++-8" diff --git a/CMakeLists.txt b/CMakeLists.txt index 414c9370bc6..1c526390682 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,14 @@ ################################################################################ # Package: AmpGen ################################################################################ -cmake_minimum_required(VERSION 3.11.1) +# cmake_minimum_required(VERSION 3.11.1) + +cmake_minimum_required(VERSION 3.9...3.15) + +if(${CMAKE_VERSION} VERSION_LESS 3.12) + cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) +endif() + project(AmpGen LANGUAGES CXX VERSION 2.1) set(AMPGEN_CXX ${CMAKE_CXX_COMPILER} CACHE FILEPATH "This should be the path to compiler (use which c++ for macOS)" ) @@ -82,8 +89,7 @@ endif() target_include_directories(AmpGen PUBLIC $ $ ) -# target_include_directories(AmpGen PUBLIC $ Date: Thu, 29 Oct 2020 09:01:54 +0100 Subject: [PATCH 240/250] maybe this time ... --- .ci/travis_linux.sh | 6 +++--- .ci/travis_osx.sh | 2 +- CMakeLists.txt | 51 ++++++++++++++++++++++++--------------------- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh index b3a17a80751..81df4e36535 100755 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -10,9 +10,9 @@ echo -en 'travis_fold:start:script.build\\r' echo "Building..." echo "Building under OS: $TRAVIS_OS_NAME, CXX =$CXX" echo "Directories: DEPS_DIR=$DEPS_DIR; TRAVIS_BUILD_DIR=$TRAVIS_BUILD_DIR" -mkdir -p build.conda -cd build.conda -cmake .. +mkdir -p build +cd build +cmake .. -DENABLE_INSTALL=0 cmake --build . -- -j2 set +evx diff --git a/.ci/travis_osx.sh b/.ci/travis_osx.sh index a670e2936a6..133a2d1d8a1 100644 --- a/.ci/travis_osx.sh +++ b/.ci/travis_osx.sh @@ -10,7 +10,7 @@ echo "Building under OS: $TRAVIS_OS_NAME" mkdir -p build cd build echo "CMake-ing, CXX = $CXX" -cmake .. -DCMAKE_CXX_COMPILER=clang -DUSE_SIMD=0 -DUSE_OPENMP=0 +cmake .. -DCMAKE_CXX_COMPILER=clang -DUSE_SIMD=0 -DUSE_OPENMP=0 -DENABLE_INSTALL=0 echo "Building ..." cmake --build . -- -j2 cd .. diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c526390682..1d2115511fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ set(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") # flag to use open set(USE_MVEC TRUE CACHE BOOL "USE_MVEC") # flag to use vector math library mvec set(ENABLE_FITTING TRUE CACHE BOOL "ENABLE_FITTING") # flag to enable fitting (requires Minuit2) set(BUILTIN_GSL TRUE CACHE BOOL "BUILTIN_GSL") # flag to use ROOT's builtin GSL +set(ENABLE_INSTALL TRUE CACHE BOOL "ENABLE_INSTALL") # flag to enable installs (switched off to make Travis happier) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") @@ -259,27 +260,29 @@ configure_package_config_file(AmpGenConfig.cmake.in PATH_VARS INCLUDE_INSTALL_DIR LIB_INSTALL_DIR DATA_INSTALL_DIR ) -install( FILES ${CMAKE_CURRENT_BINARY_DIR}/AmpGenConfig.cmake - ${CMAKE_CURRENT_BINARY_DIR}/AmpGenVersion.cmake - DESTINATION ${CMAKE_INSTALL_DATADIR}/AmpGen/cmake) - -install( - TARGETS ${PROJECT_NAME} - EXPORT AmpGenTargets - LIBRARY DESTINATION lib - PUBLIC_HEADER DESTINATION AmpGen -) - -install( - TARGETS AmpGen.exe - DESTINATION bin -) - -install(EXPORT "AmpGenTargets" - NAMESPACE "AmpGen::" - DESTINATION ${CMAKE_INSTALL_DATADIR}/AmpGen/cmake -) - -export( TARGETS AmpGen NAMESPACE AmpGen:: FILE AmpGenTargets.cmake ) -set(CMAKE_EXPORT_PACKAGE_REGISTRY ON) -export(PACKAGE AmpGen) +if( ENABLE_INSTALL ) + install( FILES ${CMAKE_CURRENT_BINARY_DIR}/AmpGenConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/AmpGenVersion.cmake + DESTINATION ${CMAKE_INSTALL_DATADIR}/AmpGen/cmake) + + install( + TARGETS ${PROJECT_NAME} + EXPORT AmpGenTargets + LIBRARY DESTINATION lib + PUBLIC_HEADER DESTINATION AmpGen + ) + + install( + TARGETS AmpGen.exe + DESTINATION bin + ) + + install(EXPORT "AmpGenTargets" + NAMESPACE "AmpGen::" + DESTINATION ${CMAKE_INSTALL_DATADIR}/AmpGen/cmake + ) + + export( TARGETS AmpGen NAMESPACE AmpGen:: FILE AmpGenTargets.cmake ) + set(CMAKE_EXPORT_PACKAGE_REGISTRY ON) + export(PACKAGE AmpGen) +endif() From 99625c3cbf9985561223e90b1d3be3d3eb05db07 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 29 Oct 2020 09:38:09 +0100 Subject: [PATCH 241/250] fix ci --- .ci/travis_linux.sh | 2 +- CMakeLists.txt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.ci/travis_linux.sh b/.ci/travis_linux.sh index 81df4e36535..e63c2fbfd9d 100755 --- a/.ci/travis_linux.sh +++ b/.ci/travis_linux.sh @@ -19,5 +19,5 @@ set +evx cd .. -./build.conda/bin/AmpGen.exe options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 10000 +./build/bin/AmpGen.exe options/example_b2kstarll.opt --CompilerWrapper::Verbose --nEvents 10000 diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d2115511fe..4884bc9f3b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,8 +49,8 @@ configure_file ("${PROJECT_SOURCE_DIR}/AmpGen/Version.h.in" "${CMAKE_BINARY_DIR} add_library(${PROJECT_NAME} SHARED ${AMPGEN_SRC} ${AMPGEN_HDR}) add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) -message( STATUS "ROOT_LIBRARIES: ${ROOT_LIBRARIES}") -message( STATUS "GSL_LIBRARIES: ${GSL_LIBRARIES}") +# message( STATUS "ROOT_LIBRARIES: ${ROOT_LIBRARIES}") +# message( STATUS "GSL_LIBRARIES: ${GSL_LIBRARIES}") if(NOT DEFINED ROOT_LIBRARIES) if(DEFINED ENV{ROOTSYS}) @@ -62,7 +62,7 @@ else() separate_arguments(ROOT_LIBRARIES) endif() -if( NOT BUILTIN_GSL ) +if( NOT BUILTIN_GSL OR DEFINED GSL_LIBRARIES ) if( NOT DEFINED GSL_LIBRARIES ) find_package(GSL) else() @@ -200,7 +200,7 @@ elseif ( ${USE_SIMD} MATCHES "AVX512d" ) else() target_compile_definitions(AmpGen PUBLIC "ENABLE_AVX=0") target_compile_options(AmpGen PUBLIC -march=x86-64) - message("SIMD disabled, resorting to scalar build : ${USE_SIMD}") + message(STATUS "SIMD disabled, resorting to scalar build : ${USE_SIMD}") endif() if(${CMAKE_CXX_COMPILER_ID} MATCHES "AppleClang" OR From 3be90cc4923a27c97200bf6cc8222cba0e19dc1a Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 29 Oct 2020 10:09:06 +0100 Subject: [PATCH 242/250] cleanup of CMakeLists --- CMakeLists.txt | 29 +++++++++++++---------------- doc/release.notes | 5 ----- src/ParticleProperties.cpp | 14 -------------- src/Utilities.cpp | 6 +++--- 4 files changed, 16 insertions(+), 38 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4884bc9f3b0..8946ef0b6c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,6 @@ ################################################################################ # Package: AmpGen ################################################################################ -# cmake_minimum_required(VERSION 3.11.1) cmake_minimum_required(VERSION 3.9...3.15) @@ -26,6 +25,7 @@ set(USE_SIMD "AVX2d" CACHE STRING "USE_SIMD") # AVX instruction set(USE_OPENMP TRUE CACHE BOOL "USE_OPENMP") # flag to use openmp for threading set(USE_MVEC TRUE CACHE BOOL "USE_MVEC") # flag to use vector math library mvec set(ENABLE_FITTING TRUE CACHE BOOL "ENABLE_FITTING") # flag to enable fitting (requires Minuit2) +set(ENABLE_TESTS TRUE CACHE BOOL "ENABLE_TESTS") # flag to build unit tests set(BUILTIN_GSL TRUE CACHE BOOL "BUILTIN_GSL") # flag to use ROOT's builtin GSL set(ENABLE_INSTALL TRUE CACHE BOOL "ENABLE_INSTALL") # flag to enable installs (switched off to make Travis happier) set(CMAKE_CXX_EXTENSIONS OFF) @@ -75,8 +75,6 @@ if( USE_OPENMP ) find_package(OpenMP) endif() -cmake_print_variables(CMAKE_SOURCE_DIR) - # Default build type from the Kitware Blog set(default_build_type "Release") if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) @@ -153,8 +151,6 @@ if( DEFINED TBB_LIBRARIES ) target_link_libraries(AmpGen PUBLIC ${TBB_LIBRARIES}) endif() -set(RAPIDSIM_DATA "") - # Default to XROOTD only if on CMT system. Can be overridden with -DAMPGEN_XROOTD=ON if(DEFINED ENV{CMTCONFIG}) set(AMPGEN_XROOTD_DEFAULT ON) @@ -219,8 +215,9 @@ else() target_compile_options(AmpGen PUBLIC -Wno-suggest-override) endif() -file(GLOB_RECURSE applications apps/*.cpp examples/*.cpp ) +# build the applications and examples +file(GLOB_RECURSE applications apps/*.cpp examples/*.cpp ) foreach( file ${applications} ) get_filename_component( Executable ${file} NAME_WE ) add_executable(${Executable}.exe ${file}) @@ -229,27 +226,27 @@ foreach( file ${applications} ) target_include_directories(${Executable}.exe PRIVATE ${ROOT_INCLUDE_DIRS}) endforeach() +# symlink the options files (so as there is the mass_width etc.) to the build directory, and also the release notes file(GLOB_RECURSE options_files options/*.*) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/bin") foreach(file ${options_files}) get_filename_component(OptionFile "${file}" NAME) execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${file}" "${CMAKE_BINARY_DIR}/bin/${OptionFile}") endforeach() +execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_SOURCE_DIR}/doc/release.notes" "${CMAKE_BINARY_DIR}/bin/release.notes") + +if( ENABLE_TESTS ) + enable_testing() + set(Boost_NO_BOOST_CMAKE ON) + add_subdirectory(test) +endif() -enable_testing() -set(Boost_NO_BOOST_CMAKE ON) -add_subdirectory(test) + +# stuff related to export, install and version tagging include(CMakePackageConfigHelpers) write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/AmpGenVersion.cmake VERSION ${PACKAGE_VERSION} COMPATIBILITY AnyNewerVersion) -set(exported_targets_name "${PROJECT_NAME}Targets") -set(exported_targets_filename "${exported_targets_name}.cmake") -set(export_dirpath "lib/cmake/cppuuid") -set(config_basename "${PROJECT_NAME}Config") -set(config_filename "${config_basename}.cmake") -set(version_filename "${config_basename}Version.cmake") - set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}) set(LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}) set(DATA_INSTALL_DIR ${CMAKE_INSTALL_DATADIR}/AmpGen) diff --git a/doc/release.notes b/doc/release.notes index 9d3af77ce0c..cd850f12407 100644 --- a/doc/release.notes +++ b/doc/release.notes @@ -1,8 +1,3 @@ -!----------------------------------------------------------------------------- -! Package : Gen/AmpGen -! Responsible : Tim Evans -! Purpose : -!----------------------------------------------------------------------------- !=================== AmpGen v2r1 2020-28-10 ================== - Improved cmake configuration to allow installation - Consolidation of Generator and ConvertToSourceCode to single executable 'AmpGen' diff --git a/src/ParticleProperties.cpp b/src/ParticleProperties.cpp index bba59dd93d7..6c0417df61a 100644 --- a/src/ParticleProperties.cpp +++ b/src/ParticleProperties.cpp @@ -100,20 +100,6 @@ bool ParticleProperties::antiThis() swapChars( m_chargeString, '+', '-'); m_charge *= -1; if( isFermion() ) m_parity *= -1; - /* - if ( !m_quarks.empty() ){ - swapChars(m_quarks, 'U', 'u'); - swapChars(m_quarks, 'D', 'd'); - swapChars(m_quarks, 'C', 'c'); - swapChars(m_quarks, 'S', 's'); - swapChars(m_quarks, 'T', 't'); - swapChars(m_quarks, 'B', 'b'); - unsigned int pos = m_quarks.find( "SqrT" ); - if ( pos < m_quarks.size() ) { - m_quarks.replace( pos, 4, "sqrt" ); - } - } - */ m_quarkContent.antiThis(); m_pdgID *= -1; return true; diff --git a/src/Utilities.cpp b/src/Utilities.cpp index 60ba141d84e..68b82afd9a8 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -290,9 +290,9 @@ void AmpGen::printSplash() #endif std::cout << " " << __DATE__ << " " << __TIME__ << bold_off << "\n\n"; - - char* AmpGenRoot = getenv("AMPGENROOT"); - if( AmpGenRoot != nullptr ) printReleaseNotes( std::string(AmpGenRoot) + "/doc/release.notes"); + #ifdef AMPGENROOT_CMAKE + printReleaseNotes( std::string(AMPGENROOT_CMAKE) + "/release.notes"); + #endif } bool AmpGen::fileExists( const std::string& name ) From 0dffdf072c11d649c13457c70f606635c7217f42 Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 30 Oct 2020 10:22:51 +0100 Subject: [PATCH 243/250] Add fallback option to take AMPGENROOT from build if undefined --- src/Utilities.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Utilities.cpp b/src/Utilities.cpp index 68b82afd9a8..7f29e030160 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -334,7 +334,11 @@ std::string AmpGen::expandGlobals( std::string path ) end_pos--; } const char* global_var = getenv( variable_name.c_str() ); - if ( global_var == nullptr ) { + if ( variable_name == "AMPGENROOT" && global_var == nullptr ) + { + global_var = AMPGENROOT; + } + else if ( global_var == nullptr ) { ERROR( "variable " << variable_name << " not found" ); break; } From 0d404065122aeca05e42222e022576a9d1b92a7b Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 30 Oct 2020 14:26:42 +0100 Subject: [PATCH 244/250] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6789ffbffdd..c9546318431 100644 --- a/README.md +++ b/README.md @@ -204,7 +204,7 @@ AmpGen.exe --help The output includes a tree (DalitzEventList) of candidates with the full four-vectors, as well as one- and two-dimensional projections, an example of which is shown below:

- +

Several models for different decays published by the LHCb collaboration are included in the options directory, in addition to several other decay modes to demonstrate different features. These options often do not include EventTypes so as they can be included as part of a larger decay chain if required. For example, to generate toy decays, the type of the events requested must also be specified: @@ -228,8 +228,8 @@ The flag `Type` is used to specify that the initial and/or final states includes

- - + +

@@ -251,8 +251,8 @@ Two example projections are shown below, of the dimuon invariant mass with essen

- - + +

From 0a35a14b818c75cee1a5e3020d0a6ac59529d8ed Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 30 Oct 2020 15:08:19 +0100 Subject: [PATCH 245/250] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c9546318431..75c5c8cee01 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ AmpGen supports several different types of probability density functions (PDFs), ##### CoherentSum -The most common type of PDF is the CoherentSum. In this case, the total amplitude is given by the sum of amplitudes, weighted by complex coefficients. At a position in the phase space , the transition amplitude is given by: +The most common type of PDF is the CoherentSum. In this case, the total amplitude is given by the sum of amplitudes, weighted by complex coefficients. At a position in the phase space , the transition amplitude is given by: From 57c9a4818a25e0ac36a2fb571a1eb57b0788b99c Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Thu, 14 Jan 2021 09:47:46 +0100 Subject: [PATCH 246/250] improve store for functions that return multiple values --- AmpGen/CompiledExpression.h | 76 +++++++++++++++++++--------------- AmpGen/Integrator.h | 2 +- AmpGen/Store.h | 22 +++++----- AmpGen/Utilities.h | 32 +++++++------- AmpGen/gsl_wrapper.h | 15 +++++++ CMakeLists.txt | 3 -- README.tex.md | 13 +++--- src/AmplitudeRules.cpp | 9 ++-- src/ExpressionParser.cpp | 67 ++++++++++++++++++++++++++---- src/Lineshapes/kMatrix.cpp | 2 +- src/Particle.cpp | 23 ++++++---- src/ParticlePropertiesList.cpp | 15 ++----- src/PhaseSpace.cpp | 1 - src/PolarisedSum.cpp | 6 +-- src/TreePhaseSpace.cpp | 5 ++- src/Wigner.cpp | 1 + 16 files changed, 186 insertions(+), 106 deletions(-) diff --git a/AmpGen/CompiledExpression.h b/AmpGen/CompiledExpression.h index 245c275ce09..cd0cf58e4ed 100644 --- a/AmpGen/CompiledExpression.h +++ b/AmpGen/CompiledExpression.h @@ -10,16 +10,17 @@ #include "AmpGen/Utilities.h" #include "AmpGen/Types.h" #include "AmpGen/simd/utils.h" +#include "AmpGen/Tensor.h" +#include "AmpGen/ArgumentPack.h" #include #include #include #include -#include "ArgumentPack.h" namespace AmpGen { /* @class CompiledExpression - @tparam RETURN_TYPE The type that is returned this compiled expression, + @tparam ret_type The type that is returned this compiled expression, usually this is a std::complex, but in principal support also exists for computing coupled channel propagators (i.e. returning array types) */ @@ -32,23 +33,24 @@ namespace AmpGen } DECLARE_ARGUMENT(disableBatch, bool); - template class CompiledExpression; + template class CompiledExpression; - template - class CompiledExpression : public CompiledExpressionBase + template + class CompiledExpression : public CompiledExpressionBase { private: - DynamicFCN m_fcn; - DynamicFCN m_batchFcn; - DynamicFCN>(ARGS...)> m_fdb; + DynamicFCN m_fcn; + DynamicFCN m_batchFcn; + DynamicFCN>(arg_types...)> m_fdb; std::vector m_externals = {}; bool m_hasExternalsChanged = {false}; public: - typedef RETURN_TYPE return_type; - + typedef ret_type return_type; + unsigned m_outputSize = {0}; + template CompiledExpression( const Expression& expression, const std::string& name, const namedArgs&... args ) : CompiledExpressionBase(expression, name) { @@ -69,22 +71,30 @@ namespace AmpGen this->m_enableBatch = false; #endif resolve(mps); + if constexpr(std::is_same::value ) + { + typedef typename std::remove_pointer>::type zt; + m_outputSize = detail::size_of::value; + DEBUG( "one element: " << m_outputSize << type_string() ); + if( is(expression) ) m_outputSize *= cast(expression).tensor().size(); + } + else m_outputSize = detail::size_of::value; } - CompiledExpression( const std::string& name = "" ) : CompiledExpressionBase( name ) {}; + CompiledExpression( const std::string& name = "" ) : CompiledExpressionBase( name ) { m_outputSize = detail::size_of::value; }; std::vector externBuffer() const { return m_externals ; } - std::string returnTypename() const override { return type_string(); } + std::string returnTypename() const override { return type_string(); } std::string fcnSignature() const override { - return CompiledExpressionBase::fcnSignature(typelist(), use_rto()); + return CompiledExpressionBase::fcnSignature(typelist(), use_rto()); } bool use_rto() const override { - return std::is_same::value; + return std::is_same::value; } std::string args() const override { std::string signature; - auto argTypes = typelist(); + auto argTypes = typelist(); for( unsigned int i = 0 ; i < argTypes.size(); ++i ) { signature += " x"+std::to_string(i) ; @@ -150,8 +160,8 @@ namespace AmpGen stream << " const size_t& N, " << " const size_t& eventSize, " << " const size_t& cacheSize, "; - stream << type_string() << " * rt, "; - stream << CompiledExpressionBase::fcnSignature(typelist(), use_rto(), false) << ") {\n"; + stream << type_string() << " * rt, "; + stream << CompiledExpressionBase::fcnSignature(typelist(), use_rto(), false) << ") {\n"; stream << "#pragma omp parallel for\n"; stream << "for( size_t i = 0; i < N/" << utils::size::value << "; ++i ){\n"; if( use_rto() ) stream << progName() + "( r + cacheSize * i, s, x0, x1 + i * eventSize);"; @@ -172,22 +182,22 @@ namespace AmpGen bool isReady() const override { return m_fcn.isLinked(); } bool isLinked() const { return m_fcn.isLinked() ; } - unsigned returnTypeSize() const override { return detail::size_of::value; } + unsigned returnTypeSize() const override { return m_outputSize; } - template < class T > - RETURN_TYPE operator()( const T* event ) const + template < typename T > + ret_type operator()( const T* event ) const { return m_fcn( m_externals.data(), event ); } - RETURN_TYPE operator()( const ARGS&... args ) const + ret_type operator()( const arg_types&... args ) const { return m_fcn( args... ); } - template void batch( arg_types... args ) const { + template void batch( batch_arg_types... args ) const { m_batchFcn(args...); } - template < class T> void debug( const T* event ) const + template < typename T> void debug( const T* event ) const { if ( !m_fcn.isLinked() ) { FATAL( "Function " << name() << " not linked" ); @@ -196,7 +206,7 @@ namespace AmpGen FATAL( "Function" << name() << " debugging symbols not linked" ); } std::vector> debug_results; - if constexpr(std::is_same::value) debug_results = m_fdb( nullptr, 0, &( m_externals[0] ), event ); + if constexpr(std::is_same::value) debug_results = m_fdb( nullptr, 0, &( m_externals[0] ), event ); else debug_results = m_fdb( &(m_externals[0]), event); for( auto& debug_result : debug_results ){ auto val = debug_result.second; @@ -223,35 +233,35 @@ namespace AmpGen }; std::string arg_type(const unsigned& i ) const override { - return typelist()[i]; + return typelist()[i]; } }; - template - CompiledExpression + template + CompiledExpression make_rto_expression( const Expression& expression, const std::string& name , const bool& verbose=false) { - CompiledExpression rt(expression,name); + CompiledExpression rt(expression,name); rt.compile(); rt.prepare(); return rt; } - template CompiledExpression + template CompiledExpression make_expression( const Expression& expression, const std::string& name , const bool& verbose=false) { - CompiledExpression rt(expression,name); + CompiledExpression rt(expression,name); rt.compile(); rt.prepare(); return rt; } - template - CompiledExpression + template + CompiledExpression make_expression( const Expression& expression, const std::string& name, const arg_types&... args) { - CompiledExpression rt(expression,name,args...); + CompiledExpression rt(expression,name,args...); rt.compile(); rt.prepare(); return rt; diff --git a/AmpGen/Integrator.h b/AmpGen/Integrator.h index d7856376028..df48b7a763d 100644 --- a/AmpGen/Integrator.h +++ b/AmpGen/Integrator.h @@ -32,7 +32,7 @@ namespace AmpGen WARNING("No events specified, returning"); return; } - m_cache = Store(events->size(), expressions, size_of ); + m_cache = Store(events->size(), expressions); m_weight.resize( events->nBlocks() ); float_v norm_acc = 0.; for( size_t i = 0 ; i < events->nBlocks(); ++i ) diff --git a/AmpGen/Store.h b/AmpGen/Store.h index 425b29433fd..92bad6b08b8 100644 --- a/AmpGen/Store.h +++ b/AmpGen/Store.h @@ -23,40 +23,40 @@ namespace AmpGen { m_store(m_nBlocks * m_nFields) {} template - void addFunctor( const functor_type& functor, unsigned fieldsPerFunctor=0 ) + void addFunctor( const functor_type& functor ) { if( m_index.count(functor.name()) == 0 ) { - auto vsize = fieldsPerFunctor == 0 ? functor.returnTypeSize() / sizeof(stored_type) : fieldsPerFunctor; - DEBUG("Registering: " << functor.name() << " field = " << m_nFields ); + auto vsize = functor.returnTypeSize() / sizeof(stored_type); + DEBUG("Registering: " << functor.name() << " field = " << m_nFields << " " << functor.returnTypeSize() << " / " << sizeof(stored_type) ); m_index[ functor.name() ] = std::make_pair(m_nFields, vsize); m_nFields += vsize; } } - template void allocate( const size_t& nEntries, const std::vector& functors, const size_t& fieldsPerFunctor = 0) + template void allocate( const size_t& nEntries, const std::vector& functors) { - for(const auto& functor : functors) addFunctor( functor, fieldsPerFunctor); + for(const auto& functor : functors) addFunctor( functor ); m_nEntries = nEntries; m_nBlocks = utils::aligned_size(nEntries)/utils::size::value; m_store.resize(m_nBlocks * m_nFields); } template ::value>::type > - void allocate( const size_t& nEntries, const functor_type& functor, const size_t& fieldsPerFunctor = 0) + void allocate( const size_t& nEntries, const functor_type& functor) { - addFunctor(functor, fieldsPerFunctor); + addFunctor(functor); m_nEntries = nEntries; m_nBlocks = utils::aligned_size(nEntries)/utils::size::value; m_store.resize(m_nBlocks * m_nFields); } - template Store( const size_t& nEntries, const std::vector& functors, const size_t& fieldsPerFunctor = 0) + template Store( const size_t& nEntries, const std::vector& functors) { - allocate(nEntries, functors, fieldsPerFunctor); + allocate(nEntries, functors); } template ::value>::type> - Store( const size_t& nEntries, const functor_type& functor, const size_t& fieldsPerFunctor=0 ) + Store( const size_t& nEntries, const functor_type& functor) { - allocate( nEntries, {functor}, fieldsPerFunctor); + allocate( nEntries, {functor}); } inline stored_type operator[]( const size_t& index ) const { return m_store[index]; } diff --git a/AmpGen/Utilities.h b/AmpGen/Utilities.h index 07ef1580995..213591f10a9 100644 --- a/AmpGen/Utilities.h +++ b/AmpGen/Utilities.h @@ -20,11 +20,12 @@ #include "AmpGen/MetaUtils.h" namespace AmpGen { - template - std::string vectorToString( it_type begin, - it_type end, + template + std::string vectorToString( iterator_type begin, + iterator_type end, const std::string& delim, - F fcn ) + functor_type fcn ) { std::stringstream ss; if( begin == end ) return ""; @@ -33,13 +34,16 @@ namespace AmpGen { ss << fcn(*(end-1)); return ss.str(); } - template > - std::string vectorToString( const std::vector& obj, const std::string& delim = "", F f = [](const T& arg){ return arg; }) + + template > + std::string vectorToString( const container_type& obj, const std::string& delim = "", const functor_type& f = [](const auto& arg){ return arg; }) { - return vectorToString( std::begin(obj), std::end(obj), delim, f); + return vectorToString( std::begin(obj), std::end(obj), delim, f); } - template std::vector> nCr( const T& n, const T& r ) + template std::vector> nCr( const T& n, const T& r ) { std::vector mask( n ); std::vector> combinations; @@ -79,13 +83,13 @@ namespace AmpGen { std::string numberWithError( const double& number, const double& error, const unsigned int& nDigits ); - template - RETURN_TYPE lexical_cast( const std::string& word, bool& status ) + template + return_type lexical_cast( const std::string& word, bool& status ) { - WARNING( "Only use specialised versions of this template (word = " << word << ", type = " << AmpGen::type_string() + WARNING( "Only use specialised versions of this template (word = " << word << ", type = " << AmpGen::type_string() << ") " ); status = 0; - return RETURN_TYPE(); + return return_type(); } template @@ -107,8 +111,8 @@ namespace AmpGen { template <> unsigned long int lexical_cast( const std::string& word, bool& status ); template <> long int lexical_cast( const std::string& word, bool& status ); - template - void processFile( const std::string& filename, FCN&& toDo, const char ignoreLinesThatBeginWith = '#' ) + template + void processFile( const std::string& filename, functor_type&& toDo, const char ignoreLinesThatBeginWith = '#' ) { std::string tmp; std::ifstream inFile( filename.c_str() ); diff --git a/AmpGen/gsl_wrapper.h b/AmpGen/gsl_wrapper.h index 04bcc9306ee..57228b24f7f 100644 --- a/AmpGen/gsl_wrapper.h +++ b/AmpGen/gsl_wrapper.h @@ -14,6 +14,21 @@ namespace AmpGen { if( ws == nullptr ) gsl_integration_workspace_free (w); return result; } + template double integrate_1d_inf( const function_type& fcn, gsl_integration_workspace* ws = nullptr) + { + gsl_integration_workspace* w = (ws == nullptr) ? gsl_integration_workspace_alloc (1000) : ws; + double result = 0; + double error = 0; + gsl_function F; + F.function = [](double x, void* p) -> double { return (*static_cast(p))(x); }; + F.params = const_cast(&fcn); + gsl_integration_qagi(&F, 0, 1e-5, 1000, w, &result, &error); + if( ws == nullptr ) gsl_integration_workspace_free (w); + std::cout << result << " +/- " << error << std::endl; + return result; + } + + template double integrate_2d( const function_type& fcn, const double& x1, const double& x2, const double& y1, const double& y2) { gsl_integration_workspace* w1 = gsl_integration_workspace_alloc (1000); diff --git a/CMakeLists.txt b/CMakeLists.txt index 8946ef0b6c3..1cea6e70ded 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,9 +49,6 @@ configure_file ("${PROJECT_SOURCE_DIR}/AmpGen/Version.h.in" "${CMAKE_BINARY_DIR} add_library(${PROJECT_NAME} SHARED ${AMPGEN_SRC} ${AMPGEN_HDR}) add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) -# message( STATUS "ROOT_LIBRARIES: ${ROOT_LIBRARIES}") -# message( STATUS "GSL_LIBRARIES: ${GSL_LIBRARIES}") - if(NOT DEFINED ROOT_LIBRARIES) if(DEFINED ENV{ROOTSYS}) list(APPEND CMAKE_MODULE_PATH "$ENV{ROOTSYS}/etc/cmake/") diff --git a/README.tex.md b/README.tex.md index 7f4daedb2a6..4ebda4aca94 100644 --- a/README.tex.md +++ b/README.tex.md @@ -204,9 +204,10 @@ AmpGen.exe --help The output includes a tree (DalitzEventList) of candidates with the full four-vectors, as well as one- and two-dimensional projections, an example of which is shown below:

- +

+ Several models for different $D^0$ decays published by the LHCb collaboration are included in the options directory, in addition to several other decay modes to demonstrate different features. These options often do not include EventTypes so as they can be included as part of a larger decay chain if required. For example, to generate $10^6$ toy $\Dz\to\Km\pip\pip\pim$ decays, the type of the events requested must also be specified: ```shell @@ -228,11 +229,12 @@ The flag `Type` is used to specify that the initial and/or final states includes

- - + +

+ #### Phase space generators Generating events consists of two phases. Firstly, the kinematics of candidates are generated according to some distribution, by default uniform in the phase space. The target distribution, $\mathcal{P}(\mathbf{x})$ , is then obtained using the accept-reject method. A candidate generated at position $\mathbf{x}$ in the phase space is retained on the condition that @@ -251,11 +253,12 @@ Two example projections are shown below, of the dimuon invariant mass with essen

- - + +

+ ### Debugger The debugger application is a tool for producing verbose information debugging for amplitudes and models. It is used on an options file as diff --git a/src/AmplitudeRules.cpp b/src/AmplitudeRules.cpp index cabb04e1b49..b3d56e136a4 100644 --- a/src/AmplitudeRules.cpp +++ b/src/AmplitudeRules.cpp @@ -57,16 +57,19 @@ Coupling::Coupling(MinuitExpression* expression) : AmplitudeRules::AmplitudeRules( const MinuitParameterSet& mps ) { for ( auto& it_re : mps ) { - if ( it_re->name().find("_Re") != std::string::npos ){ - auto it_im = mps.find(replaceAll( it_re->name(), "_Re","_Im") ); + auto& name = it_re->name(); + DEBUG("Attempting to parse: " << it_re->name() ); + if ( name.find("_Re") != std::string::npos ){ + auto it_im = mps.find(replaceAll( name, "_Re","_Im") ); if( it_im == nullptr ){ ERROR("Cannot find matching imaginary part / phase for: " << it_re->name() ); continue; } + if( ! Particle::isValidDecayDescriptor( name.substr(0, name.find("_Re") ) ) ) continue; Coupling p(it_re, it_im); m_rules[p.head()].emplace_back(p); } - else if( it_re->name().find("_Im") == std::string::npos ){ + else if( name.find("_Im") == std::string::npos ){ bool isCoupling = Particle::isValidDecayDescriptor( it_re->name() ); if( isCoupling ){ MinuitExpression* expression = dynamic_cast( it_re ); diff --git a/src/ExpressionParser.cpp b/src/ExpressionParser.cpp index 5b230478dbb..4c9c2cba2b8 100644 --- a/src/ExpressionParser.cpp +++ b/src/ExpressionParser.cpp @@ -11,6 +11,7 @@ #include "AmpGen/ASTResolver.h" #include "AmpGen/enum.h" #include "AmpGen/NamedParameter.h" +#include "AmpGen/Tensor.h" using namespace AmpGen; using namespace std::complex_literals; @@ -49,22 +50,55 @@ void ExpressionParser::processUnaryOperators( std::vector& opCodes, } } -std::vector::const_iterator findMatchingBracket( - std::vector::const_iterator begin, - std::vector::const_iterator end ) +using iterator = std::vector::const_iterator; + +template iterator findMatchingBracket(iterator begin, iterator end ) { int openedBrackets = 1; if( begin + 1 >= end ) return end; for( auto it = begin+1; it != end; ++it ) { - if( *it == "(") openedBrackets++; - if( *it == ")" ) openedBrackets--; + openedBrackets += ( it->at(0) == open) -( it->at(0) == close ); if( openedBrackets == 0 ) return it; } - ERROR("Unmatched brace in expression"); + for( auto it = begin; it != end; ++it ) + { + std::cout << *it << " "; + } + std::cout << std::endl; + FATAL("Unmatched brace in expression, " << open << " " << close); return end; } +/// divides strings by a delimiter, allowing for bracketing rules +std::vector< std::pair > split_it( iterator begin, iterator end, const std::string& delimiter) +{ + std::vector> rt; + rt.emplace_back(begin, nullptr); + int b1l = 0; + int b2l = 0; + for( auto it = begin; it != end-1; ++it ) + { + b1l += ( it->at(0) == '(') - (it->at(0) == ')'); + b2l += ( it->at(0) == '{') - (it->at(0) == '}'); + if( *it == delimiter && b1l == 0 && b2l == 0 ) + { + rt.rbegin()->second = it; + // INFO( *it << " " << std::distance( begin, rt.rbegin()->first) << " " << std::distance( begin, rt.rbegin()->second) ); + rt.emplace_back( it+1, nullptr ); + } + } + rt.rbegin()->second = end; + return rt; +} + +std::string merge( iterator begin, iterator end) +{ + std::string total = ""; + for( auto it = begin; it != end; ++it ) total += *it + " "; + return total; +} + Expression ExpressionParser::parseTokens(std::vector::const_iterator begin, std::vector::const_iterator end, const MinuitParameterSet* mps ) @@ -73,22 +107,37 @@ Expression ExpressionParser::parseTokens(std::vector::const_iterato std::vector expressions; for( auto it = begin; it != end; ++it ) { - if( *it == "(" ){ + if( it->at(0) == '(' ){ auto begin_2 = it; - auto end_2 = findMatchingBracket(it, end); + auto end_2 = findMatchingBracket<'(',')'>(it, end); expressions.emplace_back( parseTokens(begin_2+1, end_2, mps) ); it = end_2; } + else if ( it->at(0) == '{' ) + { + auto begin_2 = it; + auto end_2 = findMatchingBracket<'{','}'>(it, end); + auto divided = split_it( begin_2+1, end_2, ","); + Tensor v( std::vector{static_cast(divided.size())} ); + for( unsigned int i = 0 ; i != divided.size(); ++i ) + { + v[i] = parseTokens( divided[i].first, divided[i].second, mps); + } + DEBUG( "Adding tensor: " << v.to_string() ); + expressions.emplace_back(TensorExpression(v)); + it = end_2; + } else { auto f = std::find_if(m_binaryFunctions.begin(), m_binaryFunctions.end(), [it](auto& jt){ return jt.first == *it; } ); if( f != m_binaryFunctions.end() || m_unaryFunctions.count(*it) ) opCodes.push_back(*it); else expressions.push_back( processEndPoint( *it , mps ) ); } } + DEBUG( "nExpressions = " << expressions.size() << " nOpCodes = " << opCodes.size() << " " << vectorToString( opCodes, " " ) ); processUnaryOperators( opCodes, expressions ); processBinaryOperators( opCodes, expressions ); if( expressions.size() != 1 ){ - ERROR("Could not process expression!"); + ERROR("Could not process expression: n = " << expressions.size() << " " << merge(begin, end) ); } return expressions[0]; } diff --git a/src/Lineshapes/kMatrix.cpp b/src/Lineshapes/kMatrix.cpp index 5ba105bd98d..5fb6569a98e 100644 --- a/src/Lineshapes/kMatrix.cpp +++ b/src/Lineshapes/kMatrix.cpp @@ -184,6 +184,6 @@ DEFINE_LINESHAPE( kMatrix ) DEBUG( "Returning bkg term" ); return F[{1, pTerm}] * ( 1 - s0_prod ) / ( sInGeV - s0_prod ); } - ERROR( "Lineshape not found: " << lineshapeModifier ); + ERROR( "Modifier not found: " << lineshapeModifier << ", expecting one of {scatt, pole, poleKK, prod, prodKK}" ); return Expression( 0 ); } diff --git a/src/Particle.cpp b/src/Particle.cpp index b03103ec569..5cdd8fb1ba2 100644 --- a/src/Particle.cpp +++ b/src/Particle.cpp @@ -107,14 +107,21 @@ Particle::Particle( const std::string& decayString, const std::vectorsecond; if ( !quiet ) { - auto particleNames = ParticlePropertiesList::getMe()->getParticleNames(); - - unsigned int minDistance = 9999; - std::string suggestion = ""; - for ( auto& particle : particleNames ) { - unsigned int distance = editDistance( particle, name ); - if ( distance < minDistance ) { - suggestion = particle; - minDistance = distance; - } - } - ERROR( "Particle: " << name << " not in PDG. Did you mean " << suggestion << "?" ); + auto suggestion = std::min_element( std::begin(m_byName), std::end(m_byName), + [&name](const auto& p1, const auto& p2 ){ return editDistance(p1.first, name) < editDistance(p2.first,name); } ); + ERROR( "Particle: " << name << " not in PDG. Did you mean " << suggestion->first << "?" ); } return nullptr; } diff --git a/src/PhaseSpace.cpp b/src/PhaseSpace.cpp index 0722b162d2c..7fcb9c6c201 100644 --- a/src/PhaseSpace.cpp +++ b/src/PhaseSpace.cpp @@ -62,7 +62,6 @@ Event PhaseSpace::makeEvent() wt *= pd[n]; } } while ( wt < m_rand->Rndm() ); - rt[0] = 0; rt[1] = pd[0]; rt[2] = 0; diff --git a/src/PolarisedSum.cpp b/src/PolarisedSum.cpp index 1dab616bbc8..c9a5b44a607 100644 --- a/src/PolarisedSum.cpp +++ b/src/PolarisedSum.cpp @@ -241,7 +241,7 @@ void PolarisedSum::setEvents( EventList_type& events ) reset(); if( m_events != nullptr && m_ownEvents ) delete m_events; m_events = &events; - m_cache . allocate( m_events->size(), m_matrixElements, m_dim.first * m_dim.second ); + m_cache . allocate( m_events->size(), m_matrixElements); m_pdfCache . allocate( m_events->size(), m_probExpression); } @@ -489,7 +489,7 @@ double PolarisedSum::getWeight() const { return m_weight ; } std::function PolarisedSum::evaluator(const EventList_type* ievents) const { auto events = ievents == nullptr ? m_integrator.events() : ievents; - Store store(events->size(), m_matrixElements, m_dim.first * m_dim.second); + Store store(events->size(), m_matrixElements); for( auto& me : m_matrixElements ) store.update(events->store(), me ); std::vector values( events->aligned_size() ); @@ -511,7 +511,7 @@ KeyedFunctors PolarisedSum::componentEvaluator(const EventList_ty std::shared_ptr cache; if( events != m_integrator.events() ) { - cache = std::make_shared(events->size(), m_matrixElements, m_dim.first*m_dim.second); + cache = std::make_shared(events->size(), m_matrixElements); for( auto& me : m_matrixElements ) const_cast(cache.get())->update(events->store(), me); } else cache = std::shared_ptr( & m_integrator.cache(), [](const store_t* t){} ); diff --git a/src/TreePhaseSpace.cpp b/src/TreePhaseSpace.cpp index e1447a1ea16..b20ea5cf42a 100644 --- a/src/TreePhaseSpace.cpp +++ b/src/TreePhaseSpace.cpp @@ -119,13 +119,13 @@ TreePhaseSpace::Vertex::Vertex(const Particle& particle, const double& min, cons , max(max) , s(bwMass*bwMass) { + INFO( particle << " [" << min << ", " << max << "]"); if( particle.isStable() ) type = Type::Stable; else if( particle.isQuasiStable() ) type = Type::QuasiStable; else if( particle.lineshape().find("BW") != std::string::npos ){ type = Type::BW; phiMin = atan((min*min - bwMass*bwMass)/(bwMass*bwWidth)); phiMax = atan((max*max - bwMass*bwMass)/(bwMass*bwWidth)); - INFO( particle << " [" << min << ", " << max << "] Φ = " << phiMin << ", " << phiMax ); } else type = Type::Flat; if( index != 999 ) indices = {index}; @@ -222,7 +222,8 @@ void TreePhaseSpace::Vertex::generateFullEvent() double pf = p(); if( std::isnan(pf) || std::isnan(s) ) { - ERROR("Generating nan: " << pf << " " << s << " " << min << " " << max ); + auto p2 = ( s - 2 * (left->s+right->s) + (left->s-right->s)*(left->s-right->s)/s ); + ERROR("Generating nan: " << pf << " " << s << " " << min << " " << max << " " << p2 << " " << left->s << " " << right->s ); } left -> mom.SetXYZT( pf*sinTheta*cosPhi, pf*sinTheta*sinPhi, pf*cosTheta, sqrt(left->s + pf*pf) ); left -> mom.Boost( mom.BoostVector() ); diff --git a/src/Wigner.cpp b/src/Wigner.cpp index 9a676900334..fedfc671a21 100644 --- a/src/Wigner.cpp +++ b/src/Wigner.cpp @@ -246,6 +246,7 @@ Expression AmpGen::helicityAmplitude(const Particle& particle, } const TransformSequence& myFrame = (*cachePtr)[key]; + if( particle.isStable() ) { if( particle.props()->twoSpin() == 0 ) return Mz==0; // a scalar From 8fc07f98ef8d2069f3e5533b021d464602570fde Mon Sep 17 00:00:00 2001 From: tevans1260 Date: Fri, 15 Jan 2021 08:34:24 +0100 Subject: [PATCH 247/250] fix mistaken error message in TreePhaseSpace (scalar builds only) --- src/TreePhaseSpace.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/TreePhaseSpace.cpp b/src/TreePhaseSpace.cpp index b20ea5cf42a..09cc1266705 100644 --- a/src/TreePhaseSpace.cpp +++ b/src/TreePhaseSpace.cpp @@ -54,14 +54,13 @@ Event TreePhaseSpace::makeEvent() double w = 0; Event event; do { - // INFO("Producing event from tree: " << j ); j = m_dice(m_gen); if( j >= m_top.size() ) ERROR("Out of bounds: " << j << " / " << m_top.size() ); m_top[j].generate(); - event = m_top[j].event(m_type.size()); w = m_top[j].weight(); - event.setGenPdf( w == 0 ? 0 : genPdf(event) / w ); } while ( w == 0 ); + event = m_top[j].event(m_type.size()); + event.setGenPdf( genPdf(event) / w ); m_generatorRecord.push_back(j); return event; } @@ -223,7 +222,7 @@ void TreePhaseSpace::Vertex::generateFullEvent() if( std::isnan(pf) || std::isnan(s) ) { auto p2 = ( s - 2 * (left->s+right->s) + (left->s-right->s)*(left->s-right->s)/s ); - ERROR("Generating nan: " << pf << " " << s << " " << min << " " << max << " " << p2 << " " << left->s << " " << right->s ); + ERROR("Generating nan: " << pf << " " << s << " " << min << " " << max << " " << p2 << " " << left->s << " " << right->s << " w = " << weight() ); } left -> mom.SetXYZT( pf*sinTheta*cosPhi, pf*sinTheta*sinPhi, pf*cosTheta, sqrt(left->s + pf*pf) ); left -> mom.Boost( mom.BoostVector() ); From 5f3cb40d8ac5a9b5c185be665f087d9f964ccbd0 Mon Sep 17 00:00:00 2001 From: phdargen Date: Wed, 20 Jan 2021 17:47:18 +0100 Subject: [PATCH 248/250] added new lineshapes,spin factors --- AmpGen/Lineshapes.h | 4 + AmpGen/Vertex.h | 18 ++++- src/Lineshapes/Bugg.cpp | 55 ++++++++++++- src/Lineshapes/GounarisSakurai.cpp | 20 ++++- src/Lineshapes/PolyNR.cpp | 12 +++ src/Vertex.cpp | 124 +++++++++++++++++++++++++++-- 6 files changed, 222 insertions(+), 11 deletions(-) diff --git a/AmpGen/Lineshapes.h b/AmpGen/Lineshapes.h index 9c36c384e74..cf9a57b7309 100644 --- a/AmpGen/Lineshapes.h +++ b/AmpGen/Lineshapes.h @@ -296,6 +296,9 @@ namespace AmpGen */ DECLARE_LINESHAPE( Flatte ); DECLARE_LINESHAPE( Bugg ); + DECLARE_LINESHAPE( Kappa ); + DECLARE_LINESHAPE( Dabba ); + DECLARE_LINESHAPE( Isotensor ); /// Exponential form-factor of type \f$ e^{ - q^2 R^2 } \f$ @@ -322,6 +325,7 @@ namespace AmpGen /** @ingroup Lineshapes class Poly * @brief Polynominal shape \f$ \mathcal{A}(s) = \sum^n_i c_i s^{i} \f$ where the sum is to lineshapeModifier::Degree, and the free parameters of the shape are lineshapeModifier_ci */ + DECLARE_LINESHAPE( EXPNR ); DECLARE_LINESHAPE( PolyNR ); /** @ingroup Lineshapes class PolyNR diff --git a/AmpGen/Vertex.h b/AmpGen/Vertex.h index b78b8a7def8..57d28ebffa3 100644 --- a/AmpGen/Vertex.h +++ b/AmpGen/Vertex.h @@ -106,6 +106,7 @@ namespace AmpGen /// \ingroup Vertices class S_TT_S /// \brief \f$ S = T_1^{\mu\nu} T_{2\mu\nu}\f$ DECLARE_VERTEX( S_TT_S ); + /// @ingroup Vertices class V_SS_P /// @brief @f$ V^{\mu} = L^{\mu} S_1 S_2 @f$ @@ -119,17 +120,29 @@ namespace AmpGen DECLARE_VERTEX( V_VS_D ); DECLARE_VERTEX( V_TS_P ); DECLARE_VERTEX( V_TS_D ); - + + DECLARE_VERTEX( V_VV_S ); DECLARE_VERTEX( V_VV_P ); DECLARE_VERTEX( V_VV_P1 ); DECLARE_VERTEX( V_VV_P2 ); - DECLARE_VERTEX( V_VV_S ); + DECLARE_VERTEX( V_VV_D ); + DECLARE_VERTEX( V_VV_D2 ); DECLARE_VERTEX( T_VS_D ); DECLARE_VERTEX( T_VS_P ); DECLARE_VERTEX( T_SS_D ); DECLARE_VERTEX( T_TS_D ); DECLARE_VERTEX( T_TS_S ); + + DECLARE_VERTEX( T_VV_S ); + DECLARE_VERTEX( T_VV_P ); + DECLARE_VERTEX( T_VV_P2 ); + DECLARE_VERTEX( T_VV_D ); + DECLARE_VERTEX( T_VV_D1 ); + DECLARE_VERTEX( T_VV_D2 ); + + DECLARE_VERTEX( S_HS_F ); + DECLARE_VERTEX( H_SS_F ); DECLARE_VERTEX( f_fS_S ); DECLARE_VERTEX( f_fS_S1 ); @@ -193,6 +206,7 @@ namespace AmpGen where @f$ L_{\mu} @f$ is the Orbital_PWave operator and @f$ S_{\mu\nu} @f$ is the Spin1Projector. */ Tensor Orbital_DWave(const Tensor& p, const Tensor& q); + Tensor Orbital_FWave(const Tensor& p, const Tensor& q); /** @ingroup Vertices function Spin1Projector @brief Helper function that computes the projection operator onto a spin one state. diff --git a/src/Lineshapes/Bugg.cpp b/src/Lineshapes/Bugg.cpp index c3612d3fec7..cac67e5b0b8 100644 --- a/src/Lineshapes/Bugg.cpp +++ b/src/Lineshapes/Bugg.cpp @@ -43,7 +43,7 @@ Expression Gamma_4pi( const Expression& s, const Expression& m0, const Expressio DEFINE_LINESHAPE( Bugg ) { - Expression M = Parameter( "Bugg::M", 0.935 ); + Expression M = Parameter( "Bugg::M", 0.953 ); Expression b1 = Parameter( "Bugg::b1", 1.302 ); Expression b2 = Parameter( "Bugg::b2", 0.340 ); Expression A = Parameter( "Bugg::A", 2.426 ); @@ -97,3 +97,56 @@ DEFINE_LINESHAPE( Bugg ) ADD_DEBUG( rho_4pi( s, lambda_4pi, s0_4pi ), dbexpressions ); return lineshapeModifier == "Az" ? BW * ( s - sA ) * g1sg : BW; } + +DEFINE_LINESHAPE( Kappa ) +{ + Expression M = Parameter( "Kappa::M", 3.3 ); + Expression b1 = Parameter( "Kappa::b1", 24.49 ); + Expression b2 = Parameter( "Kappa::b2", 0. ); + Expression A = Parameter( "Kappa::A", 2.5 ); + Constant mPiPlus( 0.139570 ); + Constant mKPlus( 0.493677 ); + Expression J = Constant(0,1); + Expression sA = Parameter( "Kappa::sA", 1.) * (mKPlus*mKPlus - 0.5 * mPiPlus * mPiPlus); + + Expression g1sg = M * ( b1 + b2 * s ) * Exp( -( s - M * M ) / A ); + Expression adlerZero = ( s - sA ) / ( M * M - sA ); + Expression Gamma_tot = g1sg * adlerZero * rho_2(s,(mPiPlus+mKPlus)*(mPiPlus+mKPlus)/4.); + + Expression iBW = M * M - s - J * Gamma_tot; + + Expression BW = 1. / iBW; + ADD_DEBUG( M, dbexpressions ); + ADD_DEBUG( g1sg, dbexpressions ); + ADD_DEBUG( sA, dbexpressions ); + ADD_DEBUG( adlerZero, dbexpressions ); + ADD_DEBUG( Gamma_tot, dbexpressions ); + ADD_DEBUG( s, dbexpressions ); + ADD_DEBUG( iBW, dbexpressions ); + return lineshapeModifier == "Az" ? BW * ( s - sA ) * g1sg : BW; +} + +DEFINE_LINESHAPE( Dabba ) +{ + Expression b = Parameter( "Dabba::b", 24.49 ); + Expression alpha = Parameter( "Dabba::alpha", 0.1 ); + Expression beta = Parameter( "Dabba::beta", 0.1 ); + Constant mPiPlus( 0.139570 ); + Constant mDPlus( 1.86965 ); + Expression J = Constant(0,1); + Expression sA = Parameter( "Dabba::sA", 1.) * (mDPlus*mDPlus - 0.5 * mPiPlus * mPiPlus); + + Expression s0 = (mDPlus+mPiPlus)*(mDPlus+mPiPlus); + Expression term1 = beta * (s-s0); + Expression term2 = b * rho_2(s,s0/4.) * (s-sA) * Exp( - alpha * ( s - s0) ); + + Expression iBW = 1 - term1 - J * term2; + + Expression BW = 1. / iBW; + ADD_DEBUG( s0, dbexpressions ); + ADD_DEBUG( term1, dbexpressions ); + ADD_DEBUG( term2, dbexpressions ); + ADD_DEBUG( iBW, dbexpressions ); + return BW; +} + diff --git a/src/Lineshapes/GounarisSakurai.cpp b/src/Lineshapes/GounarisSakurai.cpp index 4db2c02832f..7366da8ae48 100644 --- a/src/Lineshapes/GounarisSakurai.cpp +++ b/src/Lineshapes/GounarisSakurai.cpp @@ -52,5 +52,23 @@ DEFINE_LINESHAPE( GounarisSakurai ) ADD_DEBUG( FormFactor , dbexpressions); ADD_DEBUG( M2 , dbexpressions); ADD_DEBUG( D, dbexpressions); - return kFactor( mass, width0, dbexpressions ) * FormFactor / (D-s); + Expression GS = kFactor( mass, width0, dbexpressions ) * FormFactor / (D-s); + if(lineshapeModifier.find("Omega") != std::string::npos){ + auto props_omega = ParticlePropertiesList::get("omega(782)0"); + Expression mass_omega = Parameter("omega(782)0_mass", props_omega->mass() ); + Expression radius_omega = Parameter("omega(782)0_radius", props_omega->radius() ); + Expression width0_omega = Parameter("omega(782)0_width", props_omega->width() ); + + const Expression kF_omega = kFactor( mass_omega, width0_omega ) ; + const Expression BW_omega = kF_omega / ( mass_omega * mass_omega - s - 1i*mass_omega * width0_omega ); + + Expression delta_Re = Parameter( "RhoOmega::deltaRe", 0. ); + Expression delta_Im = Parameter( "RhoOmega::deltaIm", 0. ); + // Expression delta_Amp = Parameter( "RhoOmega::deltaAmp", 0. ); + // Expression delta_Phase = Parameter( "RhoOmega::deltaPhase", 0. ); + // Expression delta = delta_Amp * exp(1i* M_PI / 180 * delta_Phase); + + return GS * (1.+s/(mass_omega*mass_omega) * (delta_Re + 1i*delta_Im) * BW_omega); + } +return GS; } diff --git a/src/Lineshapes/PolyNR.cpp b/src/Lineshapes/PolyNR.cpp index 7f1c0a49a91..066c2abcdf4 100644 --- a/src/Lineshapes/PolyNR.cpp +++ b/src/Lineshapes/PolyNR.cpp @@ -38,3 +38,15 @@ DEFINE_GENERIC_SHAPE( PolyNR ) } return rt; } + +DEFINE_LINESHAPE( EXPNR ) +{ + Expression alpha = Parameter( particleName + "_alpha", 0 ); + Expression beta = Parameter( particleName + "_beta", 0 ); + + const Expression BW = Exp(-alpha * s - Constant(0,1) * beta * s); + + ADD_DEBUG( BW, dbexpressions ); + return BW; +} + diff --git a/src/Vertex.cpp b/src/Vertex.cpp index 4640697854c..ab2a5578a7d 100644 --- a/src/Vertex.cpp +++ b/src/Vertex.cpp @@ -73,6 +73,16 @@ Tensor AmpGen::Orbital_DWave(const Tensor& p, const Tensor& q) return f; } +Tensor AmpGen::Orbital_FWave(const Tensor& p, const Tensor& q) +{ + Tensor L = Orbital_PWave(p, q); + Tensor f = L(mu) * L(nu) * L(alpha) - make_cse( dot( L, L ) / 5. ) * ( Spin1Projector(p) ( mu, nu ) * L(alpha) + Spin1Projector(p) ( mu, alpha ) * L(nu) + Spin1Projector(p) ( alpha, nu ) * L(mu) ) ; + f.imposeSymmetry({0,1,2}); + f.st(); + return f; +} + + Tensor AmpGen::Spin1Projector( const Tensor& P ) { auto is = 1./make_cse( dot(P,P) , true); @@ -178,6 +188,14 @@ DEFINE_VERTEX( V_VS_D ) return ( Sv( mu, nu ) * L_2_V0( -nu, -alpha ) * V1( alpha ) ) * V2[0]; } +DEFINE_VERTEX( V_VV_S ) +{ + Tensor Sv = Spin1Projector( P ); + Tensor term = LeviCivita()( -mu, -nu, -alpha, -beta ) * P( nu )/GeV * V1( alpha ) * V2( beta ); + + return term( -mu ) * Sv(mu, nu); +} + DEFINE_VERTEX( V_VV_P ) { Tensor L = Orbital_PWave( P, Q )/GeV; @@ -190,27 +208,46 @@ DEFINE_VERTEX( V_VV_P1 ) Tensor Sv = Spin1Projector( P ); Tensor term = LeviCivita()( -mu, -nu, -alpha, -beta ) * P( nu )/GeV * V1( alpha ) * V2( beta ); Tensor phi_1 = term(-mu) * Sv(mu,nu); + + Tensor term2 = LeviCivita()( -mu, -nu, -alpha, -beta ) * P( mu )/GeV * L(nu) * phi_1(alpha); - return LeviCivita()( -mu, -nu, -alpha, -beta ) * P( mu )/GeV * L(nu) * phi_1(alpha); + return Sv(mu,nu) * term2(-mu); } DEFINE_VERTEX( V_VV_P2 ) { Tensor L = Orbital_PWave( P, Q )/GeV; - Tensor Sv = Spin2Projector( P ); - Tensor phi_2 = Sv(-mu,-nu,alpha,beta) * V1(mu) * V2(nu); + Tensor Sv1 = Spin1Projector( P ); + Tensor Sv2 = Spin2Projector( P ); + Tensor phi_2 = Sv2(-mu,-nu,alpha,beta) * V1(mu) * V2(nu); - return L(-mu) * phi_2(mu,nu); + return Sv1(mu,nu) * L(alpha) * phi_2(-nu,-alpha); } -DEFINE_VERTEX( V_VV_S ) +DEFINE_VERTEX( V_VV_D ) { Tensor Sv = Spin1Projector( P ); + Tensor L = Orbital_DWave( P, Q )/(GeV*GeV); + Tensor term = LeviCivita()( -mu, -nu, -alpha, -beta ) * P( nu )/GeV * V1( alpha ) * V2( beta ); - - return term( -mu ) * Sv(mu, nu); + Tensor phi_1 = term(-mu) * Sv(mu,nu); + + return Sv(mu,nu) * L(-nu,-alpha) * phi_1(alpha); } +DEFINE_VERTEX( V_VV_D2 ) +{ + Tensor Sv1 = Spin1Projector( P ); + Tensor Sv2 = Spin2Projector( P ); + Tensor L = Orbital_DWave( P, Q )/(GeV*GeV); + + Tensor phi_2 = Sv2(-mu,-nu,alpha,beta) * V1(mu) * V2(nu); + + Tensor term = L(mu,nu) * phi_2(alpha,-mu); + Tensor term2 = LeviCivita()( -mu, -nu, -alpha, -beta ) * P( mu )/GeV * term(alpha,beta); + + return Sv1(mu,nu) * term2(-nu); +} DEFINE_VERTEX( T_VS_D ) { @@ -237,6 +274,69 @@ DEFINE_VERTEX( T_VS_P ) DEFINE_VERTEX( T_SS_D ) { return Orbital_DWave( P, Q ) * V1[0] * V2[0] / ( GeV * GeV ); } +DEFINE_VERTEX( T_VV_S ){ return Spin2Projector(P)(mu,nu,alpha,beta) * V1(-alpha) * V2(-beta); } + +DEFINE_VERTEX( T_VV_P ) +{ + Tensor Sv1 = Spin1Projector( P ); + Tensor Sv2 = Spin2Projector( P ); + Tensor L = Orbital_PWave( P, Q )/GeV; + + Tensor term = LeviCivita()( -mu, -nu, -alpha, -beta ) * P( nu )/GeV * V1( alpha ) * V2( beta ); + Tensor phi_1 = term(-mu) * Sv1(mu,nu); + + return Sv2(mu,nu,alpha,beta) * L(-alpha) * phi_1(-beta); +} + +DEFINE_VERTEX( T_VV_P2 ) +{ + // Doesnt seem to work + Tensor Sv2 = Spin2Projector( P ); + Tensor L = Orbital_PWave( P, Q )/GeV; + + Tensor phi_2 = Sv2(-mu,-nu,-alpha,-beta) * V1(mu) * V2(nu); + + Tensor term = LeviCivita()( -mu, -nu, -alpha, -beta ) * P( mu )/GeV * L(nu); + Tensor term2 = term(-alpha,-beta) * phi_2(alpha,-mu); + + return Sv2(mu,nu,alpha,beta) * term2(-alpha,-beta); +} + +DEFINE_VERTEX( T_VV_D ){ + + Tensor Sv2 = Spin2Projector( P ); + Tensor L = Orbital_DWave( P, Q )/(GeV*GeV); + + return Sv2(mu,nu,alpha,beta) * L(-alpha,-beta) * dot(V1,V2); +} + +DEFINE_VERTEX( T_VV_D1 ){ + // Doesnt seem to work + Tensor Sv1 = Spin1Projector( P ); + Tensor Sv2 = Spin2Projector( P ); + Tensor L = Orbital_DWave( P, Q )/(GeV*GeV); + + Tensor term = LeviCivita()( -mu, -nu, -alpha, -beta ) * P( nu )/GeV * V1( alpha ) * V2( beta ); + Tensor phi_1 = term(-mu) * Sv1(mu,nu); + + Tensor term2 = LeviCivita()( -mu, -nu, -alpha, -beta ) * P( mu )/GeV * phi_1(nu); + Tensor term3 = term2(-alpha,-beta) * L(alpha,mu); + + return Sv2(mu,nu,alpha,beta) * term3(-alpha,-beta); +} + +DEFINE_VERTEX( T_VV_D2 ){ + // Doesnt seem to work + Tensor Sv2 = Spin2Projector( P ); + Tensor L = Orbital_DWave( P, Q )/(GeV*GeV); + + Tensor phi_2 = Sv2(-mu,-nu,alpha,beta) * V1(mu) * V2(nu); + Tensor term = L(-alpha,-beta) * phi_2(beta,mu); + + return Sv2(mu,nu,alpha,beta) * term(-alpha,-beta) ; +} + + DEFINE_VERTEX( S_TV_P ) { Tensor L = Orbital_PWave( P, Q ) / GeV; @@ -272,6 +372,16 @@ DEFINE_VERTEX( V_TS_D ) return coupling( -mu, -nu ) * V1( nu, alpha ) * L( -alpha ) / ( GeV * GeV * GeV ); } +DEFINE_VERTEX( S_HS_F ) +{ + Tensor orbital = Orbital_FWave( P, Q ); + return V2[0] * Tensor( {dot( orbital, V1 ) / ( GeV * GeV * GeV)}, {1} ); +} + +DEFINE_VERTEX( H_SS_F ) { return Orbital_FWave( P, Q ) * V1[0] * V2[0] / ( GeV * GeV * GeV ); } + + + DEFINE_VERTEX( f_fS_S ) { Tensor f_fS_Sv = Spin1hProjector(P)(a,b) * V1(b) * V2[0]; From eb3e0fb73ca3ffa2e298553f40b14811e1b48d83 Mon Sep 17 00:00:00 2001 From: phdargen Date: Wed, 20 Jan 2021 18:44:03 +0100 Subject: [PATCH 249/250] clean-up --- AmpGen/Vertex.h | 4 ++-- src/Lineshapes/GounarisSakurai.cpp | 17 ++++++++--------- src/Vertex.cpp | 4 ++++ 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/AmpGen/Vertex.h b/AmpGen/Vertex.h index 57d28ebffa3..75c1255635a 100644 --- a/AmpGen/Vertex.h +++ b/AmpGen/Vertex.h @@ -136,9 +136,9 @@ namespace AmpGen DECLARE_VERTEX( T_VV_S ); DECLARE_VERTEX( T_VV_P ); - DECLARE_VERTEX( T_VV_P2 ); + //DECLARE_VERTEX( T_VV_P2 ); DECLARE_VERTEX( T_VV_D ); - DECLARE_VERTEX( T_VV_D1 ); + //DECLARE_VERTEX( T_VV_D1 ); DECLARE_VERTEX( T_VV_D2 ); DECLARE_VERTEX( S_HS_F ); diff --git a/src/Lineshapes/GounarisSakurai.cpp b/src/Lineshapes/GounarisSakurai.cpp index 7366da8ae48..ddad835df4c 100644 --- a/src/Lineshapes/GounarisSakurai.cpp +++ b/src/Lineshapes/GounarisSakurai.cpp @@ -35,7 +35,7 @@ DEFINE_LINESHAPE( GounarisSakurai ) Expression mass = Parameter( particleName + "_mass", props->mass() ); Expression radius = Parameter( particleName + "_radius", props->radius() ); Expression width0 = Parameter( particleName + "_width", props->width() ); - + Expression s0 = mass * mass; Expression t1 = 2 * s0 * q2(s) * q(s) *logTerm(s)/(sqrt(s)*fpow(q(s0),3)); @@ -54,21 +54,20 @@ DEFINE_LINESHAPE( GounarisSakurai ) ADD_DEBUG( D, dbexpressions); Expression GS = kFactor( mass, width0, dbexpressions ) * FormFactor / (D-s); if(lineshapeModifier.find("Omega") != std::string::npos){ + // this implements rho/omega mixing from https://arxiv.org/pdf/hep-ex/0112031.pdf auto props_omega = ParticlePropertiesList::get("omega(782)0"); Expression mass_omega = Parameter("omega(782)0_mass", props_omega->mass() ); - Expression radius_omega = Parameter("omega(782)0_radius", props_omega->radius() ); + //Expression radius_omega = Parameter("omega(782)0_radius", props_omega->radius() ); Expression width0_omega = Parameter("omega(782)0_width", props_omega->width() ); - const Expression kF_omega = kFactor( mass_omega, width0_omega ) ; + const Expression kF_omega = 1.;//kFactor( mass_omega, width0_omega ) ; const Expression BW_omega = kF_omega / ( mass_omega * mass_omega - s - 1i*mass_omega * width0_omega ); - Expression delta_Re = Parameter( "RhoOmega::deltaRe", 0. ); - Expression delta_Im = Parameter( "RhoOmega::deltaIm", 0. ); - // Expression delta_Amp = Parameter( "RhoOmega::deltaAmp", 0. ); - // Expression delta_Phase = Parameter( "RhoOmega::deltaPhase", 0. ); - // Expression delta = delta_Amp * exp(1i* M_PI / 180 * delta_Phase); + Expression delta_Amp = Parameter( particleName + "_deltaOmegaAmp", 0.00157 ); + Expression delta_Phase = Parameter( particleName + "_deltaOmegaPhase", 12.6 ); + Expression delta = delta_Amp * exp(1i* M_PI / 180 * delta_Phase); - return GS * (1.+s/(mass_omega*mass_omega) * (delta_Re + 1i*delta_Im) * BW_omega); + return GS * (1.+s/(mass_omega*mass_omega) * delta * BW_omega); } return GS; } diff --git a/src/Vertex.cpp b/src/Vertex.cpp index ab2a5578a7d..12a3cfab0f0 100644 --- a/src/Vertex.cpp +++ b/src/Vertex.cpp @@ -288,6 +288,7 @@ DEFINE_VERTEX( T_VV_P ) return Sv2(mu,nu,alpha,beta) * L(-alpha) * phi_1(-beta); } +/* DEFINE_VERTEX( T_VV_P2 ) { // Doesnt seem to work @@ -301,6 +302,7 @@ DEFINE_VERTEX( T_VV_P2 ) return Sv2(mu,nu,alpha,beta) * term2(-alpha,-beta); } +*/ DEFINE_VERTEX( T_VV_D ){ @@ -310,6 +312,7 @@ DEFINE_VERTEX( T_VV_D ){ return Sv2(mu,nu,alpha,beta) * L(-alpha,-beta) * dot(V1,V2); } +/* DEFINE_VERTEX( T_VV_D1 ){ // Doesnt seem to work Tensor Sv1 = Spin1Projector( P ); @@ -324,6 +327,7 @@ DEFINE_VERTEX( T_VV_D1 ){ return Sv2(mu,nu,alpha,beta) * term3(-alpha,-beta); } +*/ DEFINE_VERTEX( T_VV_D2 ){ // Doesnt seem to work From 83c736e5af8e47099ba460c84f682fece7036e00 Mon Sep 17 00:00:00 2001 From: phdargen Date: Wed, 20 Jan 2021 18:48:10 +0100 Subject: [PATCH 250/250] small fix --- AmpGen/Vertex.h | 2 +- src/Vertex.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/AmpGen/Vertex.h b/AmpGen/Vertex.h index 75c1255635a..850bfdbc4c3 100644 --- a/AmpGen/Vertex.h +++ b/AmpGen/Vertex.h @@ -139,7 +139,7 @@ namespace AmpGen //DECLARE_VERTEX( T_VV_P2 ); DECLARE_VERTEX( T_VV_D ); //DECLARE_VERTEX( T_VV_D1 ); - DECLARE_VERTEX( T_VV_D2 ); + //DECLARE_VERTEX( T_VV_D2 ); DECLARE_VERTEX( S_HS_F ); DECLARE_VERTEX( H_SS_F ); diff --git a/src/Vertex.cpp b/src/Vertex.cpp index 12a3cfab0f0..1385fa3cca8 100644 --- a/src/Vertex.cpp +++ b/src/Vertex.cpp @@ -328,7 +328,7 @@ DEFINE_VERTEX( T_VV_D1 ){ return Sv2(mu,nu,alpha,beta) * term3(-alpha,-beta); } */ - +/* DEFINE_VERTEX( T_VV_D2 ){ // Doesnt seem to work Tensor Sv2 = Spin2Projector( P ); @@ -339,7 +339,7 @@ DEFINE_VERTEX( T_VV_D2 ){ return Sv2(mu,nu,alpha,beta) * term(-alpha,-beta) ; } - +*/ DEFINE_VERTEX( S_TV_P ) {