1
0
mirror of https://github.com/paboyle/Grid.git synced 2025-06-18 07:47:06 +01:00

Compare commits

..

218 Commits

Author SHA1 Message Date
1e3fb32572 Checking in working version of Lanczos. 2017-03-21 16:45:33 -04:00
0d5af667d8 Works with CPS evolution 2017-03-21 12:40:43 -04:00
e9712bc7fb Zmobius test was wrong! (only mobius) checking in again 2017-03-16 23:04:28 -04:00
0b61f75c9e Adding ZMobius CG test 2017-03-13 00:12:43 -04:00
33edde245d Changing Dminus(Dag) to use full vectors to work correctly 2017-03-12 23:02:42 -04:00
cc773ae70c Merge pull request #89 from sunpho84/prepend_package_with_grid
Prepending PACKAGE_ with GRID_ in Config.h
2017-02-22 00:52:10 +00:00
d21c51b9be Merge pull request #88 from sunpho84/pickpoketting
now it is possible to pass {coords list} to a peek or poke
2017-02-22 00:51:33 +00:00
597a7b4b3a Merge pull request #81 from edbennett/develop
Fix misleading message: "doxygen-pdf requires doxygen-pdf"
2017-02-22 00:50:59 +00:00
041884acf0 Prepending PACKAGE_ with GRID_ in Config.h
Avoid polluting linking progr
2017-02-21 22:51:36 +01:00
15e668eef1 now it is possible to pass {coords list} to a peek or poke 2017-02-21 22:48:38 +01:00
c94133af49 Added iteration reporting to CG and mixed CG
Added ability to manually change the initial CG inner tolerance in mixed CG
Added .hpp files to filelist script
2017-02-02 17:04:42 -05:00
e7d8030a64 operator>> for serialisable enums 2017-02-01 15:51:08 -08:00
d775fbb2f9 Gammas: code cleaning and gamma_L implementation & test 2017-02-01 15:45:05 -08:00
863855f46f header fix 2017-02-01 11:59:44 -08:00
419af7610d New gamma matrices tidying: generated code is confined to Gamma.* for readability 2017-02-01 11:23:12 -08:00
7da7d263c4 typo 2017-01-30 10:53:13 -08:00
1140573027 Gamma adj fix: now in Grid namespace to avoid collisions 2017-01-30 10:53:04 -08:00
a0cfbb6e88 Merge branch 'feature/gammas' into feature/hadrons
# Conflicts:
#	.gitignore
#	lib/qcd/spin/Dirac.cc
#	scripts/filelist
2017-01-30 09:10:49 -08:00
515a26b3c6 gammas: copyright update 2017-01-30 09:07:09 -08:00
c946d3bf3f Merge branch 'develop' of github.com:edbennett/Grid into develop 2017-01-27 22:12:11 +00:00
1c68098780 fix misleading message: "doxygen-pdf requires doxygen-pdf" 2017-01-27 22:04:26 +00:00
899e685627 Merge branch 'feature/sitmo_rng' into develop 2017-01-27 14:15:56 +00:00
3bf993d81a gitignore update 2017-01-26 17:00:59 -08:00
fad743fbb1 Build system sanity check: corrected several headers not in the <Grid/*> format 2017-01-26 17:00:41 -08:00
ef8d3831eb Temporary patch the threading error in InsertSlice and ExtractSlice
Find source and fix the error
2017-01-25 18:12:04 +00:00
70ed9fc40c Updating the engine to the last version 2017-01-25 18:10:41 +00:00
4d3787db65 Hadrons fixed for new gammas, Meson only does one contraction but this’ll change in the future 2017-01-25 09:59:00 -08:00
677757cfeb Added and tested SITMO PRNG 2017-01-25 12:47:22 +00:00
05cb6d318a gammas: adjoint implemented as a symbolic operation 2017-01-24 18:07:43 -08:00
0432e30256 Gamma right multiply code fix (now passes consistency check) 2017-01-24 17:36:23 -08:00
2c3ebc1e07 .gitignore update 2017-01-24 17:35:42 -08:00
068b28af2d Extensive gamma test program 2017-01-24 17:35:29 -08:00
f7db342f49 Serialisable enums can be converted to int 2017-01-24 17:33:26 -08:00
d65e81518f Merge branch 'feature/hadrons' into develop 2017-01-24 09:21:44 -08:00
a37e71f362 New automatic implementation of gamma matrices, Meson and SeqGamma are broken 2017-01-23 19:13:43 -08:00
b7da264b0a Hadrons: Application is not storing the environment ref but calling getInstance() each time, solving a very nasty set fault on Linux/KNL 2017-01-21 13:40:23 -08:00
74ac2aa676 Merge branch 'feature/serialisation-hdf5' into feature/hadrons 2017-01-20 14:03:51 -08:00
4c75095c61 HDF5: header fix 2017-01-20 12:14:01 -08:00
afa095d33d HDF5: better complex number support 2017-01-20 12:10:41 -08:00
6b5259cc10 HDF5 detects if a name is a dataset or not without using exception catching 2017-01-20 11:03:19 -08:00
7423a352c5 HDF5: typos 2017-01-19 18:33:04 -08:00
81e66d6631 HDF5: revert back to native types 2017-01-19 18:24:53 -08:00
ade1058e5f Hdf5Type does not need to be a pointer anymore 2017-01-19 18:23:55 -08:00
6eea9e4da7 HDF5 types static initialisation is mysteriously buggy on BG/Q, changing strategy 2017-01-19 18:02:53 -08:00
2c673666da Standardisation of HDF5 types 2017-01-19 17:19:12 -08:00
d6401e6d2c Merge branch 'feature/hadrons' into develop 2017-01-19 14:10:01 -08:00
24d3d31b01 Genetic scheduler: uses insert instead of emplace for better compiler compatibility 2017-01-19 14:08:22 -08:00
5405526424 Code typo 2017-01-18 22:42:19 -08:00
f3f0b6fef9 serious rewriting of Test_serialisation, now crashes if IO inconsistent 2017-01-18 17:41:05 -08:00
654e0b0fd0 Serialisable object are now comparable with == 2017-01-18 17:40:32 -08:00
4be08ebccc debug code cleaning 2017-01-18 17:39:59 -08:00
f599cb5b17 HDF5 serial IO implemented and tested 2017-01-18 16:50:21 -08:00
a4a509497a Merge branch 'develop' of github.com:paboyle/Grid into develop 2017-01-17 16:22:22 -08:00
5803933aea First implementation of HDF5 serial IO writer, reader is still empty 2017-01-17 16:21:18 -08:00
7cf833dfe9 Fixed compilation error in tests hadrons (capital letter in dir name) 2017-01-17 11:00:54 +00:00
91a3534054 Lattice slice utilities now thread safe 2017-01-16 06:32:25 +00:00
16a8e3d0d4 gitignore update for ST3 2017-01-16 06:32:05 +00:00
41df1db811 Hadrons: number of dimensions entirely determined by the initial grid 2017-01-11 18:37:49 +00:00
3215ae6b7e Hadrons: genetic scheduler crashes in multi-thread with 1 module, multi-threading deactivated for now 2016-12-22 00:26:30 +01:00
7a85fddc7e Hadrons: modification of registration mechanism to allow for persistent caches 2016-12-22 00:25:36 +01:00
f8d11ff673 better serialisable enums (can be encapsulated into classes) 2016-12-20 12:31:49 +01:00
8a337f3070 Move cayley into mainstream tests 2016-12-18 02:35:31 +00:00
a59f5374d7 Evade warning 2016-12-18 02:23:55 +00:00
4b220972ac Warning fix 2016-12-18 02:14:17 +00:00
629f43e36c Return statement needed 2016-12-18 02:09:37 +00:00
a3172b3455 Precision error 2016-12-18 02:07:45 +00:00
3e6945cd65 Fixing AVX Z-mobius 2016-12-18 02:05:11 +00:00
87be03006a AVX 512 code broke other compiles; fixing 2016-12-18 01:45:09 +00:00
f17436fec2 Bad commit fixed 2016-12-18 01:27:34 +00:00
4d8b01b7ed Merge branch 'develop' of https://github.com/paboyle/Grid into develop 2016-12-18 00:56:57 +00:00
fa6acccf55 Zmobius asm 2016-12-18 00:56:19 +00:00
55cb22ad67 Z mobius bmark 2016-12-18 00:55:37 +00:00
67d72000e7 Hadrons: more legal banner fixes 2016-12-15 18:26:39 +00:00
80cef1c78f Hadrons: legal banner fix 2016-12-15 18:21:52 +00:00
91e98b1dd5 Merge branch 'feature/hadrons' into develop 2016-12-15 18:15:56 +00:00
b791c274b0 Revert "AVX: uninitialised variable fix"
This reverts commit c22c3db9ad.
2016-12-15 18:15:35 +00:00
596dd570c7 Linux linking fix 2016-12-15 12:26:53 +00:00
cad158e42f Hadrons: tests improvement 2016-12-14 19:41:51 +00:00
f63fac0c69 Hadrons: the XML runner can use a precomputed schedule 2016-12-14 19:41:30 +00:00
ab92de89ab Hadrons: utility to schedule a run 2016-12-14 19:41:04 +00:00
846272b037 Hadrons: option to save and load a schedule 2016-12-14 19:40:36 +00:00
f3e49e4b73 Hadrons: module templates update 2016-12-14 18:19:46 +00:00
decbb61ec1 Hadrons: XML driven program is again a binary installed with Grid 2016-12-14 18:19:24 +00:00
7e2482aad1 Hadrons: cpde cleaning 2016-12-14 18:04:21 +00:00
e1653a9f94 Hadrons: size fix in DWF module 2016-12-14 18:02:36 +00:00
ea40854e0b Hadrons: type names are demangled 2016-12-14 18:02:18 +00:00
34df71e755 Hadrons: function to save an application as an XML file 2016-12-14 18:01:56 +00:00
3af663e17b Hadrons: modules remember their factory registration name 2016-12-14 17:59:45 +00:00
c22c3db9ad AVX: uninitialised variable fix 2016-12-13 19:05:58 +00:00
013e710c7d Hadrons: 3pt function test improvement 2016-12-13 19:04:43 +00:00
16693bd69d Hadrons: scheduler heuristic benchmark 2016-12-13 19:02:32 +00:00
de8f80cf94 Hadrons: genetic operators improvement 2016-12-13 19:02:05 +00:00
4a87486365 Hadrons: a bit of cleaning in the scheduler 2016-12-10 21:14:13 +01:00
fe187e9ed3 Compiles and passes under ZMobius with assembler 2016-12-10 00:47:48 +00:00
0091b50f49 Zmobius working -- not asm yet 2016-12-09 22:51:32 +00:00
fb8d4b2357 Lots of debug on performance Mobius 2016-12-08 17:28:28 +00:00
ff71a8e847 Ready for sim 2016-12-08 17:00:32 +00:00
83fa038bdf Streaming stores 2016-12-08 16:58:42 +00:00
7a61feb6d3 Allocator added with caching for Linux VM subsystem optimisation 2016-12-08 16:58:01 +00:00
69ae817d1c Updates for supporting Mobius better 2016-12-08 16:43:28 +00:00
51322da6f8 Hadrons: genetic scheduler improvement 2016-12-07 09:00:45 +09:00
49c3eeb378 Hadrons: more verbose genetic parameters 2016-12-07 08:59:58 +09:00
c56707e003 useless debug message removed 2016-12-07 08:59:20 +09:00
5b3edf08a4 Hadrons: sequential gamma source 2016-12-06 12:13:19 +09:00
bd1d1cca34 Hadrons: code cleaning 2016-12-06 12:12:59 +09:00
646b11f5c2 Hadrons: exposing scheduler settings 2016-12-06 12:12:05 +09:00
a683a0f55a Hadrons: meson tests renamed spectrum 2016-12-06 12:11:44 +09:00
e6effcfd95 Hadrons: more contractions in the spectrum test 2016-12-05 17:41:58 +09:00
aa016f61b9 Hadrons: empty baryon contractions 2016-12-05 17:26:57 +09:00
d42a1b73c4 Hadrons: code cleaning 2016-12-05 17:26:36 +09:00
d292657ef7 Hadrons: more module templates 2016-12-05 17:26:17 +09:00
d1f7c6b94e Hadrons: templatisation of the fermion implementation 2016-12-05 16:47:29 +09:00
7ae734103e Hadrons: namespace macro to tackle GCC 5 bug 2016-12-05 14:29:32 +09:00
7a1ac45679 Hadrons: configure.ac Linux typo 2016-12-05 14:00:10 +09:00
320268fe93 Hadrons: code cleaning 2016-12-05 13:57:34 +09:00
dd6fb140c5 Hadrons: big module reorganisation 2016-12-05 13:53:31 +09:00
0b4f680d28 Hadrons: meson run test 2016-12-05 11:44:58 +09:00
a69086ba1f Hadrons: application run minor fixes 2016-12-05 11:44:36 +09:00
7433eed274 Hadrons: module creation fix 2016-12-05 11:44:16 +09:00
ee5b1fe043 Hadrons: freeing object message fix 2016-12-05 09:08:45 +09:00
1540616b22 Hadrons: integer types cleanup 2016-12-05 08:53:48 +09:00
8190523e4c Hadrons: type fix in module creation 2016-12-02 11:04:34 +09:00
b5555d85a7 Hadrons: generelalised FImpl for actions 2016-12-02 11:04:15 +09:00
9ad3d3453e Hadrons is now a library, the previous XML driven program is now a test 2016-12-01 21:36:29 +09:00
d8b716d2cd Hadrons: static initialisation fixed 2016-12-01 15:43:16 +09:00
43928846f2 first steps to make Hadrons a library 2016-11-28 16:02:15 +09:00
fabcd4179d Hadrons: propagator type coming from the fermion implementation 2016-11-28 14:02:10 +09:00
a8843c9af6 Code cleaning, the fermion implementation can be sepcified using the macro FIMPL 2016-11-27 16:47:22 +09:00
7a1a7a685e Merge branch 'feature/fft-opt' into feature/hadrons 2016-11-27 15:32:03 +09:00
1aa695cd78 Hadrons: merge typo 2016-11-10 18:38:30 +00:00
13a8997789 Merge branch 'release/v0.6.0' into feature/hadrons
# Conflicts:
#	Makefile.am
2016-11-08 20:43:39 +00:00
a034e9901b Merge branch 'develop' into feature/hadrons 2016-09-20 13:49:33 +01:00
7ff7c7d90d Merge branch 'develop' into feature/hadrons 2016-08-04 16:22:10 +01:00
a2e9430abe Hadrons: fix after build system update 2016-08-03 17:14:32 +01:00
2485ef9c9c Merge branch 'feature/new-build' into feature/hadrons
# Conflicts:
#	Makefile.am
#	scripts/copyright
2016-08-03 16:49:16 +01:00
e0b7004f96 Merge branch 'master' into feature/hadrons 2016-07-01 15:54:34 +01:00
75fc295f6e Merge branch 'hadrons' into feature/hadrons 2016-06-14 17:51:15 +01:00
0b731b5d80 Hadrons: genetic scheduler parameter fix 2016-06-06 17:46:53 +01:00
8e2078be71 Hadrons: environment with fully generic object store 2016-06-06 17:45:37 +01:00
1826ed06a3 Merge branch 'master' into hadrons 2016-05-27 16:50:31 +01:00
3ff96c502b Merge branch 'master' into hadrons 2016-05-12 19:24:18 +01:00
15a0908bfc Merge branch 'master' into hadrons 2016-05-12 18:35:46 +01:00
bb2125962b Hadrons: finished implementation of 5D quarks 2016-05-12 18:34:42 +01:00
232fda5fe1 Hadrons: DWF action 2016-05-12 18:34:10 +01:00
2b31bf61ff Hadrons: message fix 2016-05-12 18:33:49 +01:00
afe5a94745 Hadrons: getModule with upcast 2016-05-12 18:33:36 +01:00
7ae667c767 Hadrons: module template update 2016-05-12 18:33:08 +01:00
07f0b69784 Merge branch 'master' into hadrons 2016-05-12 13:02:18 +01:00
5c06e89d69 Hadrons: code cleaning 2016-05-12 12:49:49 +01:00
3d75e0f0d1 Hadrons: MQuark fix 2016-05-12 12:02:15 +01:00
362f255100 Hadrons: module parameters can now be accessed from outside 2016-05-12 11:59:28 +01:00
3d78ed03ef Merge branch 'master' into hadrons 2016-05-11 15:21:46 +01:00
835003b3c5 Hadrons: removed useless gauge global parameters 2016-05-11 15:01:52 +01:00
328d213c9e Hadrons: FS case sensitivity fix 2016-05-11 14:44:14 +01:00
56a8d7a5bc Hadrons: build system fix 2016-05-11 10:27:14 +01:00
78198d1b04 Hadrons: size fix for module graph with one vertex 2016-05-10 20:13:28 +01:00
84fa2bdce6 Hadrons: modules moved in their own directory & utility script to add new modules 2016-05-10 20:12:48 +01:00
29dfe99e7c Hadrons: more scheduler optimizations 2016-05-10 19:19:38 +01:00
d604580e5a Hadrons: all objects/modules mapped to an integer address system to remove string operations from scheduling 2016-05-10 19:07:41 +01:00
7dfdc9baa0 Hadrons: lattice dynamic cast fix 2016-05-10 10:41:20 +01:00
9e986654e6 Hadrons: first version of the genetic scheduler 2016-05-09 14:49:06 +01:00
df3fbc477e Hadrons: code cleaning 2016-05-07 13:26:56 -07:00
bb580ae077 Hadrons: significant overhaul of the object registration system, previous version didn't allow dry runs 2016-05-07 13:19:38 -07:00
2c226753ab Hadrons: comments on graph theory algorithm complexity 2016-05-06 06:35:11 -07:00
ea0cea668e Hadrons: minor code cleaning 2016-05-05 16:13:14 -07:00
75cd72a421 Hadrons: memory management for fermion matrices, dynamic ownership in garbage collector 2016-05-04 19:11:03 -07:00
cbe52b0659 Hadrons: debug message removed 2016-05-04 12:20:33 -07:00
3aa6463ede Hadrons: general lattice store & a lot of code cleaning 2016-05-04 12:17:27 -07:00
312637e5fb Merge branch 'master' into hadrons
# Conflicts:
#	lib/Log.h
2016-05-04 12:16:18 -07:00
798d8f7340 Hadrons: Modules: better log messages 2016-05-03 18:17:58 -07:00
ba878724ce Hadrons: sources are now independent modules 2016-05-03 18:17:28 -07:00
b865dd9da8 Hadrons: solver renaming 2016-05-03 18:16:57 -07:00
8b313a35ac Hadrons: random and NERSC gauge configurations 2016-05-03 17:08:42 -07:00
02ec23cdad Hadrons: Fermion actions and gauge fields are modules now 2016-05-03 17:08:42 -07:00
6e83b6a203 Hadrons: namespace reorganisation, now everything is in Grid::Hadrons, the 'using Grid::operator<<' statement is used to prevent a very nasty compilation error with GCC. 2016-05-02 19:31:21 -07:00
48fcc34d72 CMeson: first implementation, still need proper output 2016-05-01 18:31:40 -07:00
d08d93c44c Merge branch 'master' into hadrons 2016-05-01 18:30:44 -07:00
0ab10cdedb Merge branch 'master' into hadrons 2016-05-01 16:08:05 -07:00
22653edf12 Merge branch 'master' into hadrons 2016-05-01 15:55:58 -07:00
12d2a95846 Merge branch 'master' into hadrons 2016-05-01 15:05:02 -07:00
978cf52f6b Merge branch 'master' into hadrons 2016-05-01 14:53:38 -07:00
63b730de80 Hadrons: for the moment, test with unit gauge 2016-05-01 14:50:57 -07:00
7905c5b8e5 Hadrons: Z2 source code fix 2016-05-01 14:49:45 -07:00
5e4b58ac40 Hadrons: Z2 source expression fix 2016-05-01 12:49:26 -07:00
468d8dc682 Merge branch 'master' into hadrons 2016-05-01 12:03:24 -07:00
beb11fd4ef Merge branch 'master' into hadrons 2016-05-01 10:32:24 -07:00
d7662b5175 Merge branch 'master' into hadrons 2016-04-30 00:24:59 -07:00
dc5f32e5f0 Merge branch 'master' into hadrons 2016-04-30 00:18:31 -07:00
1869d28429 Hadrons: first prototype with working inversions 2016-04-30 00:17:04 -07:00
405b175665 Merge branch 'master' into hadrons 2016-04-30 00:16:06 -07:00
e33b0f6ff7 cleaner output 2016-04-16 08:41:53 +01:00
9ee54e0db7 debug output removed 2016-04-16 08:41:28 +01:00
feae35d92c Hadrons: pass strings by value 2016-04-16 08:41:12 +01:00
3834d81181 Merge branch 'master' into hadrons 2016-04-14 15:15:45 +01:00
179e82b5ca Merge branch 'master' into hadrons 2016-03-08 12:55:33 +00:00
f2c59c8730 Merge branch 'master' into hadrons 2016-03-02 17:15:05 +00:00
fdd0848593 Hadrons: license text update 2016-02-25 12:07:21 +00:00
92f666905f copyright script update to 80 column text 2016-02-25 12:06:24 +00:00
5980fa8640 test implementation of DWF inverter 2016-02-25 11:56:16 +00:00
a0d8eb2c24 minor code cleaning 2016-02-23 16:33:00 +00:00
1e10b4571d fix after Grid update 2016-02-23 16:21:45 +00:00
02f8b84ac9 Merge branch 'master' into hadrons 2016-02-23 16:13:39 +00:00
cfd368596d Merge branch 'master' into hadrons 2016-02-22 15:25:02 +00:00
ae682674e0 Hadrons: first full implementation of the scheduler 2016-01-13 20:23:51 -08:00
17c43f49ac Hadrons: application class now take parameter file name as argument 2016-01-13 20:22:37 -08:00
30146e977c gitignore update 2016-01-13 20:20:43 -08:00
54eacec261 Hadrons: namespace std not used anymore in compiled sources 2015-12-23 14:30:33 +00:00
76c78f04e2 Hadrons: first complete prototype for run loop 2015-12-23 14:21:35 +00:00
379580cd89 Merge branch 'master' into hadrons 2015-12-23 14:20:22 +00:00
14a80733f9 Merge branch 'master' into hadrons 2015-12-08 13:57:53 +00:00
d4db009a58 Hadrons: starting scheduler implementation 2015-12-07 18:26:38 +00:00
20ce7e0270 Hadrons: algorithm to determine all possible topological ordering 2015-12-07 15:46:36 +00:00
bb195607ab Hadrons: fix in topological sort algorithm name 2015-12-02 19:40:11 +00:00
6f090e22c0 Hadrons: graph topological sort 2015-12-02 19:33:34 +00:00
339e983172 Merge branch 'master' into hadrons 2015-12-02 14:38:04 +00:00
4a7f3d1b7b Merge branch 'master' into hadrons
# Conflicts:
#	configure
2015-12-02 10:57:51 +00:00
c4e2202550 First graph class implementation and test 2015-11-05 14:28:14 +00:00
538b16610b First commit for measurement software 'Hadrons' 2015-10-27 17:33:18 +00:00
174 changed files with 13914 additions and 2242 deletions

15
.gitignore vendored
View File

@ -9,6 +9,7 @@
################
*~
*#
*.sublime-*
# Precompiled Headers #
#######################
@ -103,4 +104,16 @@ lib/fftw/*
# libtool macros #
##################
m4/lt*
m4/libtool.m4
m4/libtool.m4
# Buck files #
##############
.buck*
buck-out
BUCK
make-bin-BUCK.sh
# generated sources #
#####################
lib/qcd/spin/gamma-gen/*.h
lib/qcd/spin/gamma-gen/*.cc

View File

@ -1,5 +1,5 @@
# additional include paths necessary to compile the C++ library
SUBDIRS = lib benchmarks tests
SUBDIRS = lib benchmarks tests extras
include $(top_srcdir)/doxygen.inc

View File

@ -37,11 +37,11 @@ struct scal {
d internal;
};
Gamma::GammaMatrix Gmu [] = {
Gamma::GammaX,
Gamma::GammaY,
Gamma::GammaZ,
Gamma::GammaT
Gamma::Algebra Gmu [] = {
Gamma::Algebra::GammaX,
Gamma::Algebra::GammaY,
Gamma::Algebra::GammaZ,
Gamma::Algebra::GammaT
};
typedef WilsonFermion5D<DomainWallVec5dImplR> WilsonFermion5DR;
@ -321,7 +321,7 @@ int main (int argc, char ** argv)
ref = zero;
for(int mu=0;mu<Nd;mu++){
// ref = src - Gamma(Gamma::GammaX)* src ; // 1+gamma_x
// ref = src - Gamma(Gamma::Algebra::GammaX)* src ; // 1+gamma_x
tmp = U[mu]*Cshift(src,mu+1,1);
for(int i=0;i<ref._odata.size();i++){
ref._odata[i]+= tmp._odata[i] + Gamma(Gmu[mu])*tmp._odata[i]; ;

View File

@ -37,11 +37,11 @@ struct scal {
d internal;
};
Gamma::GammaMatrix Gmu [] = {
Gamma::GammaX,
Gamma::GammaY,
Gamma::GammaZ,
Gamma::GammaT
Gamma::Algebra Gmu [] = {
Gamma::Algebra::GammaX,
Gamma::Algebra::GammaY,
Gamma::Algebra::GammaZ,
Gamma::Algebra::GammaT
};
void benchDw(std::vector<int> & L, int Ls, int threads, int report =0 );

View File

@ -113,6 +113,36 @@ int main (int argc, char ** argv)
std::cout<<GridLogMessage << "Called " #A " "<< (t1-t0)/ncall<<" us"<<std::endl;\
std::cout<<GridLogMessage << "******************"<<std::endl;
#define BENCH_ZDW(A,in,out) \
zDw.CayleyZeroCounters(); \
zDw. A (in,out); \
FGrid->Barrier(); \
t0=usecond(); \
for(int i=0;i<ncall;i++){ \
zDw. A (in,out); \
} \
t1=usecond(); \
FGrid->Barrier(); \
zDw.CayleyReport(); \
std::cout<<GridLogMessage << "Called ZDw " #A " "<< (t1-t0)/ncall<<" us"<<std::endl;\
std::cout<<GridLogMessage << "******************"<<std::endl;
#define BENCH_DW_SSC(A,in,out) \
Dw.CayleyZeroCounters(); \
Dw. A (in,out); \
FGrid->Barrier(); \
t0=usecond(); \
for(int i=0;i<ncall;i++){ \
__SSC_START ; \
Dw. A (in,out); \
__SSC_STOP ; \
} \
t1=usecond(); \
FGrid->Barrier(); \
Dw.CayleyReport(); \
std::cout<<GridLogMessage << "Called " #A " "<< (t1-t0)/ncall<<" us"<<std::endl;\
std::cout<<GridLogMessage << "******************"<<std::endl;
#define BENCH_DW_MEO(A,in,out) \
Dw.CayleyZeroCounters(); \
Dw. A (in,out,0); \
@ -148,9 +178,15 @@ int main (int argc, char ** argv)
LatticeFermion sref(sFGrid);
LatticeFermion result(sFGrid);
std::cout<<GridLogMessage << "Constructing Vec5D Dw "<<std::endl;
DomainWallFermionVec5dR Dw(Umu,*sFGrid,*sFrbGrid,*sUGrid,*sUrbGrid,mass,M5);
RealD b=1.5;// Scale factor b+c=2, b-c=1
RealD c=0.5;
std::vector<ComplexD> gamma(Ls,std::complex<double>(1.0,0.0));
ZMobiusFermionVec5dR zDw(Umu,*sFGrid,*sFrbGrid,*sUGrid,*sUrbGrid,mass,M5,gamma,b,c);
std::cout<<GridLogMessage << "Calling Dhop "<<std::endl;
FGrid->Barrier();
@ -173,10 +209,13 @@ int main (int argc, char ** argv)
BENCH_DW_MEO(Dhop ,src,result);
BENCH_DW_MEO(DhopEO ,src_o,r_e);
BENCH_DW(Meooe ,src_o,r_e);
BENCH_DW_SSC(Meooe ,src_o,r_e);
BENCH_DW(Mooee ,src_o,r_o);
BENCH_DW(MooeeInv,src_o,r_o);
BENCH_ZDW(Mooee ,src_o,r_o);
BENCH_ZDW(MooeeInv,src_o,r_o);
}
Grid_finalize();

View File

@ -37,11 +37,11 @@ struct scal {
d internal;
};
Gamma::GammaMatrix Gmu [] = {
Gamma::GammaX,
Gamma::GammaY,
Gamma::GammaZ,
Gamma::GammaT
Gamma::Algebra Gmu [] = {
Gamma::Algebra::GammaX,
Gamma::Algebra::GammaY,
Gamma::Algebra::GammaZ,
Gamma::Algebra::GammaT
};
bool overlapComms = false;
@ -106,7 +106,7 @@ int main (int argc, char ** argv)
{ // Naive wilson implementation
ref = zero;
for(int mu=0;mu<Nd;mu++){
// ref = src + Gamma(Gamma::GammaX)* src ; // 1-gamma_x
// ref = src + Gamma(Gamma::Algebra::GammaX)* src ; // 1-gamma_x
tmp = U[mu]*Cshift(src,mu,1);
for(int i=0;i<ref._odata.size();i++){
ref._odata[i]+= tmp._odata[i] - Gamma(Gmu[mu])*tmp._odata[i]; ;
@ -159,7 +159,7 @@ int main (int argc, char ** argv)
ref = zero;
for(int mu=0;mu<Nd;mu++){
// ref = src - Gamma(Gamma::GammaX)* src ; // 1+gamma_x
// ref = src - Gamma(Gamma::Algebra::GammaX)* src ; // 1+gamma_x
tmp = U[mu]*Cshift(src,mu,1);
for(int i=0;i<ref._odata.size();i++){
ref._odata[i]+= tmp._odata[i] + Gamma(Gmu[mu])*tmp._odata[i]; ;

View File

@ -30,11 +30,11 @@ struct scal {
d internal;
};
Gamma::GammaMatrix Gmu [] = {
Gamma::GammaX,
Gamma::GammaY,
Gamma::GammaZ,
Gamma::GammaT
Gamma::Algebra Gmu [] = {
Gamma::Algebra::GammaX,
Gamma::Algebra::GammaY,
Gamma::Algebra::GammaZ,
Gamma::Algebra::GammaT
};
bool overlapComms = false;

View File

@ -6,7 +6,7 @@ AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE(subdir-objects)
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([lib/Grid.h])
AC_CONFIG_HEADERS([lib/Config.h])
AC_CONFIG_HEADERS([lib/Config.h],[sed -i 's|PACKAGE_|GRID_|' lib/Config.h])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
############### Checks for programs
@ -99,6 +99,13 @@ case ${ac_MKL} in
AC_DEFINE([USE_MKL], [1], [Define to 1 if you use the Intel MKL]);;
esac
############### HDF5
AC_ARG_WITH([hdf5],
[AS_HELP_STRING([--with-hdf5=prefix],
[try this for a non-standard install prefix of the HDF5 library])],
[AM_CXXFLAGS="-I$with_hdf5/include $AM_CXXFLAGS"]
[AM_LDFLAGS="-L$with_hdf5/lib $AM_LDFLAGS"])
############### first-touch
AC_ARG_ENABLE([numa],
[AC_HELP_STRING([--enable-numa=yes|no|prefix], [enable first touch numa opt])],
@ -145,6 +152,12 @@ AC_SEARCH_LIBS([fftw_execute], [fftw3],
[AC_DEFINE([HAVE_FFTW], [1], [Define to 1 if you have the `FFTW' library])]
[have_fftw=true])
AC_SEARCH_LIBS([H5Fopen], [hdf5_cpp],
[AC_DEFINE([HAVE_HDF5], [1], [Define to 1 if you have the `HDF5' library])]
[have_hdf5=true]
[LIBS="${LIBS} -lhdf5"], [], [-lhdf5])
AM_CONDITIONAL(BUILD_HDF5, [ test "${have_hdf5}X" == "trueX" ])
CXXFLAGS=$CXXFLAGS_CPY
LDFLAGS=$LDFLAGS_CPY
@ -306,7 +319,7 @@ AM_CONDITIONAL(BUILD_COMMS_MPI3L, [ test "${comms_type}X" == "mpi3lX" ] )
AM_CONDITIONAL(BUILD_COMMS_NONE, [ test "${comms_type}X" == "noneX" ])
############### RNG selection
AC_ARG_ENABLE([rng],[AC_HELP_STRING([--enable-rng=ranlux48|mt19937],\
AC_ARG_ENABLE([rng],[AC_HELP_STRING([--enable-rng=ranlux48|mt19937|sitmo],\
[Select Random Number Generator to be used])],\
[ac_RNG=${enable_rng}],[ac_RNG=ranlux48])
@ -317,6 +330,9 @@ case ${ac_RNG} in
mt19937)
AC_DEFINE([RNG_MT19937],[1],[RNG_MT19937] )
;;
sitmo)
AC_DEFINE([RNG_SITMO],[1],[RNG_SITMO] )
;;
*)
AC_MSG_ERROR([${ac_RNG} unsupported --enable-rng option]);
;;
@ -381,10 +397,13 @@ AC_CONFIG_FILES(tests/IO/Makefile)
AC_CONFIG_FILES(tests/core/Makefile)
AC_CONFIG_FILES(tests/debug/Makefile)
AC_CONFIG_FILES(tests/forces/Makefile)
AC_CONFIG_FILES(tests/hadrons/Makefile)
AC_CONFIG_FILES(tests/hmc/Makefile)
AC_CONFIG_FILES(tests/solver/Makefile)
AC_CONFIG_FILES(tests/qdpxx/Makefile)
AC_CONFIG_FILES(benchmarks/Makefile)
AC_CONFIG_FILES(extras/Makefile)
AC_CONFIG_FILES(extras/Hadrons/Makefile)
AC_OUTPUT
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -407,6 +426,7 @@ RNG choice : ${ac_RNG}
GMP : `if test "x$have_gmp" = xtrue; then echo yes; else echo no; fi`
LAPACK : ${ac_LAPACK}
FFTW : `if test "x$have_fftw" = xtrue; then echo yes; else echo no; fi`
HDF5 : `if test "x$have_hdf5" = xtrue; then echo yes; else echo no; fi`
build DOXYGEN documentation : `if test "$DX_FLAG_doc" = '1'; then echo yes; else echo no; fi`
----- BUILD FLAGS -------------------------------------
CXXFLAGS:

View File

@ -0,0 +1,317 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Application.cc
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include <Grid/Hadrons/Application.hpp>
#include <Grid/Hadrons/GeneticScheduler.hpp>
using namespace Grid;
using namespace QCD;
using namespace Hadrons;
#define BIG_SEP "==============="
#define SEP "---------------"
/******************************************************************************
* Application implementation *
******************************************************************************/
// constructors ////////////////////////////////////////////////////////////////
Application::Application(void)
{
LOG(Message) << "Modules available:" << std::endl;
auto list = ModuleFactory::getInstance().getBuilderList();
for (auto &m: list)
{
LOG(Message) << " " << m << std::endl;
}
auto dim = GridDefaultLatt(), mpi = GridDefaultMpi(), loc(dim);
locVol_ = 1;
for (unsigned int d = 0; d < dim.size(); ++d)
{
loc[d] /= mpi[d];
locVol_ *= loc[d];
}
LOG(Message) << "Global lattice: " << dim << std::endl;
LOG(Message) << "MPI partition : " << mpi << std::endl;
LOG(Message) << "Local lattice : " << loc << std::endl;
}
Application::Application(const Application::GlobalPar &par)
: Application()
{
setPar(par);
}
Application::Application(const std::string parameterFileName)
: Application()
{
parameterFileName_ = parameterFileName;
}
// environment shortcut ////////////////////////////////////////////////////////
Environment & Application::env(void) const
{
return Environment::getInstance();
}
// access //////////////////////////////////////////////////////////////////////
void Application::setPar(const Application::GlobalPar &par)
{
par_ = par;
env().setSeed(strToVec<int>(par_.seed));
}
const Application::GlobalPar & Application::getPar(void)
{
return par_;
}
// execute /////////////////////////////////////////////////////////////////////
void Application::run(void)
{
if (!parameterFileName_.empty() and (env().getNModule() == 0))
{
parseParameterFile(parameterFileName_);
}
if (!scheduled_)
{
schedule();
}
printSchedule();
configLoop();
}
// parse parameter file ////////////////////////////////////////////////////////
class ObjectId: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(ObjectId,
std::string, name,
std::string, type);
};
void Application::parseParameterFile(const std::string parameterFileName)
{
XmlReader reader(parameterFileName);
GlobalPar par;
ObjectId id;
LOG(Message) << "Building application from '" << parameterFileName << "'..." << std::endl;
read(reader, "parameters", par);
setPar(par);
push(reader, "modules");
push(reader, "module");
do
{
read(reader, "id", id);
env().createModule(id.name, id.type, reader);
} while (reader.nextElement("module"));
pop(reader);
pop(reader);
}
void Application::saveParameterFile(const std::string parameterFileName)
{
XmlWriter writer(parameterFileName);
ObjectId id;
const unsigned int nMod = env().getNModule();
LOG(Message) << "Saving application to '" << parameterFileName << "'..." << std::endl;
write(writer, "parameters", getPar());
push(writer, "modules");
for (unsigned int i = 0; i < nMod; ++i)
{
push(writer, "module");
id.name = env().getModuleName(i);
id.type = env().getModule(i)->getRegisteredName();
write(writer, "id", id);
env().getModule(i)->saveParameters(writer, "options");
pop(writer);
}
pop(writer);
pop(writer);
}
// schedule computation ////////////////////////////////////////////////////////
#define MEM_MSG(size)\
sizeString((size)*locVol_) << " (" << sizeString(size) << "/site)"
#define DEFINE_MEMPEAK \
auto memPeak = [this](const std::vector<unsigned int> &program)\
{\
unsigned int memPeak;\
bool msg;\
\
msg = HadronsLogMessage.isActive();\
HadronsLogMessage.Active(false);\
env().dryRun(true);\
memPeak = env().executeProgram(program);\
env().dryRun(false);\
env().freeAll();\
HadronsLogMessage.Active(true);\
\
return memPeak;\
}
void Application::schedule(void)
{
DEFINE_MEMPEAK;
// build module dependency graph
LOG(Message) << "Building module graph..." << std::endl;
auto graph = env().makeModuleGraph();
auto con = graph.getConnectedComponents();
// constrained topological sort using a genetic algorithm
LOG(Message) << "Scheduling computation..." << std::endl;
LOG(Message) << " #module= " << graph.size() << std::endl;
LOG(Message) << " population size= " << par_.genetic.popSize << std::endl;
LOG(Message) << " max. generation= " << par_.genetic.maxGen << std::endl;
LOG(Message) << " max. cst. generation= " << par_.genetic.maxCstGen << std::endl;
LOG(Message) << " mutation rate= " << par_.genetic.mutationRate << std::endl;
unsigned int k = 0, gen, prevPeak, nCstPeak = 0;
std::random_device rd;
GeneticScheduler<unsigned int>::Parameters par;
par.popSize = par_.genetic.popSize;
par.mutationRate = par_.genetic.mutationRate;
par.seed = rd();
memPeak_ = 0;
CartesianCommunicator::BroadcastWorld(0, &(par.seed), sizeof(par.seed));
for (unsigned int i = 0; i < con.size(); ++i)
{
GeneticScheduler<unsigned int> scheduler(con[i], memPeak, par);
gen = 0;
do
{
LOG(Debug) << "Generation " << gen << ":" << std::endl;
scheduler.nextGeneration();
if (gen != 0)
{
if (prevPeak == scheduler.getMinValue())
{
nCstPeak++;
}
else
{
nCstPeak = 0;
}
}
prevPeak = scheduler.getMinValue();
if (gen % 10 == 0)
{
LOG(Iterative) << "Generation " << gen << ": "
<< MEM_MSG(scheduler.getMinValue()) << std::endl;
}
gen++;
} while ((gen < par_.genetic.maxGen)
and (nCstPeak < par_.genetic.maxCstGen));
auto &t = scheduler.getMinSchedule();
if (scheduler.getMinValue() > memPeak_)
{
memPeak_ = scheduler.getMinValue();
}
for (unsigned int j = 0; j < t.size(); ++j)
{
program_.push_back(t[j]);
}
}
scheduled_ = true;
}
void Application::saveSchedule(const std::string filename)
{
TextWriter writer(filename);
std::vector<std::string> program;
if (!scheduled_)
{
HADRON_ERROR("Computation not scheduled");
}
LOG(Message) << "Saving current schedule to '" << filename << "'..."
<< std::endl;
for (auto address: program_)
{
program.push_back(env().getModuleName(address));
}
write(writer, "schedule", program);
}
void Application::loadSchedule(const std::string filename)
{
DEFINE_MEMPEAK;
TextReader reader(filename);
std::vector<std::string> program;
LOG(Message) << "Loading schedule from '" << filename << "'..."
<< std::endl;
read(reader, "schedule", program);
program_.clear();
for (auto &name: program)
{
program_.push_back(env().getModuleAddress(name));
}
scheduled_ = true;
memPeak_ = memPeak(program_);
}
void Application::printSchedule(void)
{
if (!scheduled_)
{
HADRON_ERROR("Computation not scheduled");
}
LOG(Message) << "Schedule (memory peak: " << MEM_MSG(memPeak_) << "):"
<< std::endl;
for (unsigned int i = 0; i < program_.size(); ++i)
{
LOG(Message) << std::setw(4) << i + 1 << ": "
<< env().getModuleName(program_[i]) << std::endl;
}
}
// loop on configurations //////////////////////////////////////////////////////
void Application::configLoop(void)
{
auto range = par_.trajCounter;
for (unsigned int t = range.start; t < range.end; t += range.step)
{
LOG(Message) << BIG_SEP << " Starting measurement for trajectory " << t
<< " " << BIG_SEP << std::endl;
env().setTrajectory(t);
env().executeProgram(program_);
}
LOG(Message) << BIG_SEP << " End of measurement " << BIG_SEP << std::endl;
env().freeAll();
}

View File

@ -0,0 +1,132 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Application.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_Application_hpp_
#define Hadrons_Application_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Environment.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
#include <Grid/Hadrons/Modules.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* Main program manager *
******************************************************************************/
class Application
{
public:
class TrajRange: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(TrajRange,
unsigned int, start,
unsigned int, end,
unsigned int, step);
};
class GeneticPar: Serializable
{
public:
GeneticPar(void):
popSize{20}, maxGen{1000}, maxCstGen{100}, mutationRate{.1} {};
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(GeneticPar,
unsigned int, popSize,
unsigned int, maxGen,
unsigned int, maxCstGen,
double , mutationRate);
};
class GlobalPar: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(GlobalPar,
TrajRange, trajCounter,
GeneticPar, genetic,
std::string, seed);
};
public:
// constructors
Application(void);
Application(const GlobalPar &par);
Application(const std::string parameterFileName);
// destructor
virtual ~Application(void) = default;
// access
void setPar(const GlobalPar &par);
const GlobalPar & getPar(void);
// module creation
template <typename M>
void createModule(const std::string name);
template <typename M>
void createModule(const std::string name, const typename M::Par &par);
// execute
void run(void);
// XML parameter file I/O
void parseParameterFile(const std::string parameterFileName);
void saveParameterFile(const std::string parameterFileName);
// schedule computation
void schedule(void);
void saveSchedule(const std::string filename);
void loadSchedule(const std::string filename);
void printSchedule(void);
// loop on configurations
void configLoop(void);
private:
// environment shortcut
Environment & env(void) const;
private:
long unsigned int locVol_;
std::string parameterFileName_{""};
GlobalPar par_;
std::vector<unsigned int> program_;
Environment::Size memPeak_;
bool scheduled_{false};
};
/******************************************************************************
* Application template implementation *
******************************************************************************/
// module creation /////////////////////////////////////////////////////////////
template <typename M>
void Application::createModule(const std::string name)
{
env().createModule<M>(name);
}
template <typename M>
void Application::createModule(const std::string name,
const typename M::Par &par)
{
env().createModule<M>(name, par);
}
END_HADRONS_NAMESPACE
#endif // Hadrons_Application_hpp_

View File

@ -0,0 +1,743 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Environment.cc
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include <Grid/Hadrons/Environment.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
using namespace Grid;
using namespace QCD;
using namespace Hadrons;
/******************************************************************************
* Environment implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
Environment::Environment(void)
{
nd_ = GridDefaultLatt().size();
grid4d_.reset(SpaceTimeGrid::makeFourDimGrid(
GridDefaultLatt(), GridDefaultSimd(nd_, vComplex::Nsimd()),
GridDefaultMpi()));
gridRb4d_.reset(SpaceTimeGrid::makeFourDimRedBlackGrid(grid4d_.get()));
auto loc = getGrid()->LocalDimensions();
locVol_ = 1;
for (unsigned int d = 0; d < loc.size(); ++d)
{
locVol_ *= loc[d];
}
rng4d_.reset(new GridParallelRNG(grid4d_.get()));
}
// dry run /////////////////////////////////////////////////////////////////////
void Environment::dryRun(const bool isDry)
{
dryRun_ = isDry;
}
bool Environment::isDryRun(void) const
{
return dryRun_;
}
// trajectory number ///////////////////////////////////////////////////////////
void Environment::setTrajectory(const unsigned int traj)
{
traj_ = traj;
}
unsigned int Environment::getTrajectory(void) const
{
return traj_;
}
// grids ///////////////////////////////////////////////////////////////////////
void Environment::createGrid(const unsigned int Ls)
{
if (grid5d_.find(Ls) == grid5d_.end())
{
auto g = getGrid();
grid5d_[Ls].reset(SpaceTimeGrid::makeFiveDimGrid(Ls, g));
gridRb5d_[Ls].reset(SpaceTimeGrid::makeFiveDimRedBlackGrid(Ls, g));
}
}
GridCartesian * Environment::getGrid(const unsigned int Ls) const
{
try
{
if (Ls == 1)
{
return grid4d_.get();
}
else
{
return grid5d_.at(Ls).get();
}
}
catch(std::out_of_range &)
{
HADRON_ERROR("no grid with Ls= " << Ls);
}
}
GridRedBlackCartesian * Environment::getRbGrid(const unsigned int Ls) const
{
try
{
if (Ls == 1)
{
return gridRb4d_.get();
}
else
{
return gridRb5d_.at(Ls).get();
}
}
catch(std::out_of_range &)
{
HADRON_ERROR("no red-black 5D grid with Ls= " << Ls);
}
}
unsigned int Environment::getNd(void) const
{
return nd_;
}
// random number generator /////////////////////////////////////////////////////
void Environment::setSeed(const std::vector<int> &seed)
{
rng4d_->SeedFixedIntegers(seed);
}
GridParallelRNG * Environment::get4dRng(void) const
{
return rng4d_.get();
}
// module management ///////////////////////////////////////////////////////////
void Environment::pushModule(Environment::ModPt &pt)
{
std::string name = pt->getName();
if (!hasModule(name))
{
std::vector<unsigned int> inputAddress;
unsigned int address;
ModuleInfo m;
m.data = std::move(pt);
m.type = typeIdPt(*m.data.get());
m.name = name;
auto input = m.data->getInput();
for (auto &in: input)
{
if (!hasObject(in))
{
addObject(in , -1);
}
m.input.push_back(objectAddress_[in]);
}
auto output = m.data->getOutput();
module_.push_back(std::move(m));
address = static_cast<unsigned int>(module_.size() - 1);
moduleAddress_[name] = address;
for (auto &out: output)
{
if (!hasObject(out))
{
addObject(out, address);
}
else
{
if (object_[objectAddress_[out]].module < 0)
{
object_[objectAddress_[out]].module = address;
}
else
{
HADRON_ERROR("object '" + out
+ "' is already produced by module '"
+ module_[object_[getObjectAddress(out)].module].name
+ "' (while pushing module '" + name + "')");
}
}
}
}
else
{
HADRON_ERROR("module '" + name + "' already exists");
}
}
unsigned int Environment::getNModule(void) const
{
return module_.size();
}
void Environment::createModule(const std::string name, const std::string type,
XmlReader &reader)
{
auto &factory = ModuleFactory::getInstance();
auto pt = factory.create(type, name);
pt->parseParameters(reader, "options");
pushModule(pt);
}
ModuleBase * Environment::getModule(const unsigned int address) const
{
if (hasModule(address))
{
return module_[address].data.get();
}
else
{
HADRON_ERROR("no module with address " + std::to_string(address));
}
}
ModuleBase * Environment::getModule(const std::string name) const
{
return getModule(getModuleAddress(name));
}
unsigned int Environment::getModuleAddress(const std::string name) const
{
if (hasModule(name))
{
return moduleAddress_.at(name);
}
else
{
HADRON_ERROR("no module with name '" + name + "'");
}
}
std::string Environment::getModuleName(const unsigned int address) const
{
if (hasModule(address))
{
return module_[address].name;
}
else
{
HADRON_ERROR("no module with address " + std::to_string(address));
}
}
std::string Environment::getModuleType(const unsigned int address) const
{
if (hasModule(address))
{
return typeName(module_[address].type);
}
else
{
HADRON_ERROR("no module with address " + std::to_string(address));
}
}
std::string Environment::getModuleType(const std::string name) const
{
return getModuleType(getModuleAddress(name));
}
bool Environment::hasModule(const unsigned int address) const
{
return (address < module_.size());
}
bool Environment::hasModule(const std::string name) const
{
return (moduleAddress_.find(name) != moduleAddress_.end());
}
Graph<unsigned int> Environment::makeModuleGraph(void) const
{
Graph<unsigned int> moduleGraph;
for (unsigned int i = 0; i < module_.size(); ++i)
{
moduleGraph.addVertex(i);
for (auto &j: module_[i].input)
{
moduleGraph.addEdge(object_[j].module, i);
}
}
return moduleGraph;
}
#define BIG_SEP "==============="
#define SEP "---------------"
#define MEM_MSG(size)\
sizeString((size)*locVol_) << " (" << sizeString(size) << "/site)"
Environment::Size
Environment::executeProgram(const std::vector<unsigned int> &p)
{
Size memPeak = 0, sizeBefore, sizeAfter;
std::vector<std::set<unsigned int>> freeProg;
bool continueCollect, nothingFreed;
// build garbage collection schedule
freeProg.resize(p.size());
for (unsigned int i = 0; i < object_.size(); ++i)
{
auto pred = [i, this](const unsigned int j)
{
auto &in = module_[j].input;
auto it = std::find(in.begin(), in.end(), i);
return (it != in.end()) or (j == object_[i].module);
};
auto it = std::find_if(p.rbegin(), p.rend(), pred);
if (it != p.rend())
{
freeProg[p.rend() - it - 1].insert(i);
}
}
// program execution
for (unsigned int i = 0; i < p.size(); ++i)
{
// execute module
if (!isDryRun())
{
LOG(Message) << SEP << " Measurement step " << i+1 << "/"
<< p.size() << " (module '" << module_[p[i]].name
<< "') " << SEP << std::endl;
}
(*module_[p[i]].data)();
sizeBefore = getTotalSize();
// print used memory after execution
if (!isDryRun())
{
LOG(Message) << "Allocated objects: " << MEM_MSG(sizeBefore)
<< std::endl;
}
if (sizeBefore > memPeak)
{
memPeak = sizeBefore;
}
// garbage collection for step i
if (!isDryRun())
{
LOG(Message) << "Garbage collection..." << std::endl;
}
nothingFreed = true;
do
{
continueCollect = false;
auto toFree = freeProg[i];
for (auto &j: toFree)
{
// continue garbage collection while there are still
// objects without owners
continueCollect = continueCollect or !hasOwners(j);
if(freeObject(j))
{
// if an object has been freed, remove it from
// the garbage collection schedule
freeProg[i].erase(j);
nothingFreed = false;
}
}
} while (continueCollect);
// any remaining objects in step i garbage collection schedule
// is scheduled for step i + 1
if (i + 1 < p.size())
{
for (auto &j: freeProg[i])
{
freeProg[i + 1].insert(j);
}
}
// print used memory after garbage collection if necessary
if (!isDryRun())
{
sizeAfter = getTotalSize();
if (sizeBefore != sizeAfter)
{
LOG(Message) << "Allocated objects: " << MEM_MSG(sizeAfter)
<< std::endl;
}
else
{
LOG(Message) << "Nothing to free" << std::endl;
}
}
}
return memPeak;
}
Environment::Size Environment::executeProgram(const std::vector<std::string> &p)
{
std::vector<unsigned int> pAddress;
for (auto &n: p)
{
pAddress.push_back(getModuleAddress(n));
}
return executeProgram(pAddress);
}
// general memory management ///////////////////////////////////////////////////
void Environment::addObject(const std::string name, const int moduleAddress)
{
if (!hasObject(name))
{
ObjInfo info;
info.name = name;
info.module = moduleAddress;
object_.push_back(std::move(info));
objectAddress_[name] = static_cast<unsigned int>(object_.size() - 1);
}
else
{
HADRON_ERROR("object '" + name + "' already exists");
}
}
void Environment::registerObject(const unsigned int address,
const unsigned int size, const unsigned int Ls)
{
if (!hasRegisteredObject(address))
{
if (hasObject(address))
{
object_[address].size = size;
object_[address].Ls = Ls;
object_[address].isRegistered = true;
}
else
{
HADRON_ERROR("no object with address " + std::to_string(address));
}
}
else
{
HADRON_ERROR("object with address " + std::to_string(address)
+ " already registered");
}
}
void Environment::registerObject(const std::string name,
const unsigned int size, const unsigned int Ls)
{
if (!hasObject(name))
{
addObject(name);
}
registerObject(getObjectAddress(name), size, Ls);
}
unsigned int Environment::getObjectAddress(const std::string name) const
{
if (hasObject(name))
{
return objectAddress_.at(name);
}
else
{
HADRON_ERROR("no object with name '" + name + "'");
}
}
std::string Environment::getObjectName(const unsigned int address) const
{
if (hasObject(address))
{
return object_[address].name;
}
else
{
HADRON_ERROR("no object with address " + std::to_string(address));
}
}
std::string Environment::getObjectType(const unsigned int address) const
{
if (hasRegisteredObject(address))
{
return typeName(object_[address].type);
}
else if (hasObject(address))
{
HADRON_ERROR("object with address " + std::to_string(address)
+ " exists but is not registered");
}
else
{
HADRON_ERROR("no object with address " + std::to_string(address));
}
}
std::string Environment::getObjectType(const std::string name) const
{
return getObjectType(getObjectAddress(name));
}
Environment::Size Environment::getObjectSize(const unsigned int address) const
{
if (hasRegisteredObject(address))
{
return object_[address].size;
}
else if (hasObject(address))
{
HADRON_ERROR("object with address " + std::to_string(address)
+ " exists but is not registered");
}
else
{
HADRON_ERROR("no object with address " + std::to_string(address));
}
}
Environment::Size Environment::getObjectSize(const std::string name) const
{
return getObjectSize(getObjectAddress(name));
}
unsigned int Environment::getObjectLs(const unsigned int address) const
{
if (hasRegisteredObject(address))
{
return object_[address].Ls;
}
else if (hasObject(address))
{
HADRON_ERROR("object with address " + std::to_string(address)
+ " exists but is not registered");
}
else
{
HADRON_ERROR("no object with address " + std::to_string(address));
}
}
unsigned int Environment::getObjectLs(const std::string name) const
{
return getObjectLs(getObjectAddress(name));
}
bool Environment::hasObject(const unsigned int address) const
{
return (address < object_.size());
}
bool Environment::hasObject(const std::string name) const
{
auto it = objectAddress_.find(name);
return ((it != objectAddress_.end()) and hasObject(it->second));
}
bool Environment::hasRegisteredObject(const unsigned int address) const
{
if (hasObject(address))
{
return object_[address].isRegistered;
}
else
{
return false;
}
}
bool Environment::hasRegisteredObject(const std::string name) const
{
if (hasObject(name))
{
return hasRegisteredObject(getObjectAddress(name));
}
else
{
return false;
}
}
bool Environment::hasCreatedObject(const unsigned int address) const
{
if (hasObject(address))
{
return (object_[address].data != nullptr);
}
else
{
return false;
}
}
bool Environment::hasCreatedObject(const std::string name) const
{
if (hasObject(name))
{
return hasCreatedObject(getObjectAddress(name));
}
else
{
return false;
}
}
bool Environment::isObject5d(const unsigned int address) const
{
return (getObjectLs(address) > 1);
}
bool Environment::isObject5d(const std::string name) const
{
return (getObjectLs(name) > 1);
}
Environment::Size Environment::getTotalSize(void) const
{
Environment::Size size = 0;
for (auto &o: object_)
{
if (o.isRegistered)
{
size += o.size;
}
}
return size;
}
void Environment::addOwnership(const unsigned int owner,
const unsigned int property)
{
if (hasObject(property))
{
object_[property].owners.insert(owner);
}
else
{
HADRON_ERROR("no object with address " + std::to_string(property));
}
if (hasObject(owner))
{
object_[owner].properties.insert(property);
}
else
{
HADRON_ERROR("no object with address " + std::to_string(owner));
}
}
void Environment::addOwnership(const std::string owner,
const std::string property)
{
addOwnership(getObjectAddress(owner), getObjectAddress(property));
}
bool Environment::hasOwners(const unsigned int address) const
{
if (hasObject(address))
{
return (!object_[address].owners.empty());
}
else
{
HADRON_ERROR("no object with address " + std::to_string(address));
}
}
bool Environment::hasOwners(const std::string name) const
{
return hasOwners(getObjectAddress(name));
}
bool Environment::freeObject(const unsigned int address)
{
if (!hasOwners(address))
{
if (!isDryRun() and object_[address].isRegistered)
{
LOG(Message) << "Destroying object '" << object_[address].name
<< "'" << std::endl;
}
for (auto &p: object_[address].properties)
{
object_[p].owners.erase(address);
}
object_[address].size = 0;
object_[address].Ls = 0;
object_[address].isRegistered = false;
object_[address].type = nullptr;
object_[address].owners.clear();
object_[address].properties.clear();
object_[address].data.reset(nullptr);
return true;
}
else
{
return false;
}
}
bool Environment::freeObject(const std::string name)
{
return freeObject(getObjectAddress(name));
}
void Environment::freeAll(void)
{
for (unsigned int i = 0; i < object_.size(); ++i)
{
freeObject(i);
}
}
void Environment::printContent(void)
{
LOG(Message) << "Modules: " << std::endl;
for (unsigned int i = 0; i < module_.size(); ++i)
{
LOG(Message) << std::setw(4) << i << ": "
<< getModuleName(i) << std::endl;
}
LOG(Message) << "Objects: " << std::endl;
for (unsigned int i = 0; i < object_.size(); ++i)
{
LOG(Message) << std::setw(4) << i << ": "
<< getObjectName(i) << std::endl;
}
}

View File

@ -0,0 +1,385 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Environment.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_Environment_hpp_
#define Hadrons_Environment_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Graph.hpp>
#ifndef SITE_SIZE_TYPE
#define SITE_SIZE_TYPE unsigned int
#endif
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* Global environment *
******************************************************************************/
// forward declaration of Module
class ModuleBase;
class Object
{
public:
Object(void) = default;
virtual ~Object(void) = default;
};
template <typename T>
class Holder: public Object
{
public:
Holder(void) = default;
Holder(T *pt);
virtual ~Holder(void) = default;
T & get(void) const;
T * getPt(void) const;
void reset(T *pt);
private:
std::unique_ptr<T> objPt_{nullptr};
};
class Environment
{
SINGLETON(Environment);
public:
typedef SITE_SIZE_TYPE Size;
typedef std::unique_ptr<ModuleBase> ModPt;
typedef std::unique_ptr<GridCartesian> GridPt;
typedef std::unique_ptr<GridRedBlackCartesian> GridRbPt;
typedef std::unique_ptr<GridParallelRNG> RngPt;
typedef std::unique_ptr<LatticeBase> LatticePt;
private:
struct ModuleInfo
{
const std::type_info *type{nullptr};
std::string name;
ModPt data{nullptr};
std::vector<unsigned int> input;
};
struct ObjInfo
{
Size size{0};
unsigned int Ls{0};
bool isRegistered{false};
const std::type_info *type{nullptr};
std::string name;
int module{-1};
std::set<unsigned int> owners, properties;
std::unique_ptr<Object> data{nullptr};
};
public:
// dry run
void dryRun(const bool isDry);
bool isDryRun(void) const;
// trajectory number
void setTrajectory(const unsigned int traj);
unsigned int getTrajectory(void) const;
// grids
void createGrid(const unsigned int Ls);
GridCartesian * getGrid(const unsigned int Ls = 1) const;
GridRedBlackCartesian * getRbGrid(const unsigned int Ls = 1) const;
unsigned int getNd(void) const;
// random number generator
void setSeed(const std::vector<int> &seed);
GridParallelRNG * get4dRng(void) const;
// module management
void pushModule(ModPt &pt);
template <typename M>
void createModule(const std::string name);
template <typename M>
void createModule(const std::string name,
const typename M::Par &par);
void createModule(const std::string name,
const std::string type,
XmlReader &reader);
unsigned int getNModule(void) const;
ModuleBase * getModule(const unsigned int address) const;
ModuleBase * getModule(const std::string name) const;
template <typename M>
M * getModule(const unsigned int address) const;
template <typename M>
M * getModule(const std::string name) const;
unsigned int getModuleAddress(const std::string name) const;
std::string getModuleName(const unsigned int address) const;
std::string getModuleType(const unsigned int address) const;
std::string getModuleType(const std::string name) const;
bool hasModule(const unsigned int address) const;
bool hasModule(const std::string name) const;
Graph<unsigned int> makeModuleGraph(void) const;
Size executeProgram(const std::vector<unsigned int> &p);
Size executeProgram(const std::vector<std::string> &p);
// general memory management
void addObject(const std::string name,
const int moduleAddress = -1);
void registerObject(const unsigned int address,
const unsigned int size,
const unsigned int Ls = 1);
void registerObject(const std::string name,
const unsigned int size,
const unsigned int Ls = 1);
template <typename T>
unsigned int lattice4dSize(void) const;
template <typename T>
void registerLattice(const unsigned int address,
const unsigned int Ls = 1);
template <typename T>
void registerLattice(const std::string name,
const unsigned int Ls = 1);
template <typename T>
void setObject(const unsigned int address, T *object);
template <typename T>
void setObject(const std::string name, T *object);
template <typename T>
T * getObject(const unsigned int address) const;
template <typename T>
T * getObject(const std::string name) const;
template <typename T>
T * createLattice(const unsigned int address);
template <typename T>
T * createLattice(const std::string name);
unsigned int getObjectAddress(const std::string name) const;
std::string getObjectName(const unsigned int address) const;
std::string getObjectType(const unsigned int address) const;
std::string getObjectType(const std::string name) const;
Size getObjectSize(const unsigned int address) const;
Size getObjectSize(const std::string name) const;
unsigned int getObjectLs(const unsigned int address) const;
unsigned int getObjectLs(const std::string name) const;
bool hasObject(const unsigned int address) const;
bool hasObject(const std::string name) const;
bool hasRegisteredObject(const unsigned int address) const;
bool hasRegisteredObject(const std::string name) const;
bool hasCreatedObject(const unsigned int address) const;
bool hasCreatedObject(const std::string name) const;
bool isObject5d(const unsigned int address) const;
bool isObject5d(const std::string name) const;
Environment::Size getTotalSize(void) const;
void addOwnership(const unsigned int owner,
const unsigned int property);
void addOwnership(const std::string owner,
const std::string property);
bool hasOwners(const unsigned int address) const;
bool hasOwners(const std::string name) const;
bool freeObject(const unsigned int address);
bool freeObject(const std::string name);
void freeAll(void);
void printContent(void);
private:
// general
bool dryRun_{false};
unsigned int traj_, locVol_;
// grids
GridPt grid4d_;
std::map<unsigned int, GridPt> grid5d_;
GridRbPt gridRb4d_;
std::map<unsigned int, GridRbPt> gridRb5d_;
unsigned int nd_;
// random number generator
RngPt rng4d_;
// module and related maps
std::vector<ModuleInfo> module_;
std::map<std::string, unsigned int> moduleAddress_;
// lattice store
std::map<unsigned int, LatticePt> lattice_;
// object store
std::vector<ObjInfo> object_;
std::map<std::string, unsigned int> objectAddress_;
};
/******************************************************************************
* Holder template implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
template <typename T>
Holder<T>::Holder(T *pt)
: objPt_(pt)
{}
// access //////////////////////////////////////////////////////////////////////
template <typename T>
T & Holder<T>::get(void) const
{
return &objPt_.get();
}
template <typename T>
T * Holder<T>::getPt(void) const
{
return objPt_.get();
}
template <typename T>
void Holder<T>::reset(T *pt)
{
objPt_.reset(pt);
}
/******************************************************************************
* Environment template implementation *
******************************************************************************/
// module management ///////////////////////////////////////////////////////////
template <typename M>
void Environment::createModule(const std::string name)
{
ModPt pt(new M(name));
pushModule(pt);
}
template <typename M>
void Environment::createModule(const std::string name,
const typename M::Par &par)
{
ModPt pt(new M(name));
static_cast<M *>(pt.get())->setPar(par);
pushModule(pt);
}
template <typename M>
M * Environment::getModule(const unsigned int address) const
{
if (auto *pt = dynamic_cast<M *>(getModule(address)))
{
return pt;
}
else
{
HADRON_ERROR("module '" + module_[address].name
+ "' does not have type " + typeid(M).name()
+ "(object type: " + getModuleType(address) + ")");
}
}
template <typename M>
M * Environment::getModule(const std::string name) const
{
return getModule<M>(getModuleAddress(name));
}
template <typename T>
unsigned int Environment::lattice4dSize(void) const
{
return sizeof(typename T::vector_object)/getGrid()->Nsimd();
}
template <typename T>
void Environment::registerLattice(const unsigned int address,
const unsigned int Ls)
{
createGrid(Ls);
registerObject(address, Ls*lattice4dSize<T>(), Ls);
}
template <typename T>
void Environment::registerLattice(const std::string name, const unsigned int Ls)
{
createGrid(Ls);
registerObject(name, Ls*lattice4dSize<T>(), Ls);
}
template <typename T>
void Environment::setObject(const unsigned int address, T *object)
{
if (hasRegisteredObject(address))
{
object_[address].data.reset(new Holder<T>(object));
object_[address].type = &typeid(T);
}
else if (hasObject(address))
{
HADRON_ERROR("object with address " + std::to_string(address) +
" exists but is not registered");
}
else
{
HADRON_ERROR("no object with address " + std::to_string(address));
}
}
template <typename T>
void Environment::setObject(const std::string name, T *object)
{
setObject(getObjectAddress(name), object);
}
template <typename T>
T * Environment::getObject(const unsigned int address) const
{
if (hasRegisteredObject(address))
{
if (auto h = dynamic_cast<Holder<T> *>(object_[address].data.get()))
{
return h->getPt();
}
else
{
HADRON_ERROR("object with address " + std::to_string(address) +
" does not have type '" + typeid(T).name() +
"' (has type '" + getObjectType(address) + "')");
}
}
else if (hasObject(address))
{
HADRON_ERROR("object with address " + std::to_string(address) +
" exists but is not registered");
}
else
{
HADRON_ERROR("no object with address " + std::to_string(address));
}
}
template <typename T>
T * Environment::getObject(const std::string name) const
{
return getObject<T>(getObjectAddress(name));
}
template <typename T>
T * Environment::createLattice(const unsigned int address)
{
GridCartesian *g = getGrid(getObjectLs(address));
setObject(address, new T(g));
return getObject<T>(address);
}
template <typename T>
T * Environment::createLattice(const std::string name)
{
return createLattice<T>(getObjectAddress(name));
}
END_HADRONS_NAMESPACE
#endif // Hadrons_Environment_hpp_

106
extras/Hadrons/Factory.hpp Normal file
View File

@ -0,0 +1,106 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Factory.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_Factory_hpp_
#define Hadrons_Factory_hpp_
#include <Grid/Hadrons/Global.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* abstract factory class *
******************************************************************************/
template <typename T>
class Factory
{
public:
typedef std::function<std::unique_ptr<T>(const std::string)> Func;
public:
// constructor
Factory(void) = default;
// destructor
virtual ~Factory(void) = default;
// registration
void registerBuilder(const std::string type, const Func &f);
// get builder list
std::vector<std::string> getBuilderList(void) const;
// factory
std::unique_ptr<T> create(const std::string type,
const std::string name) const;
private:
std::map<std::string, Func> builder_;
};
/******************************************************************************
* template implementation *
******************************************************************************/
// registration ////////////////////////////////////////////////////////////////
template <typename T>
void Factory<T>::registerBuilder(const std::string type, const Func &f)
{
builder_[type] = f;
}
// get module list /////////////////////////////////////////////////////////////
template <typename T>
std::vector<std::string> Factory<T>::getBuilderList(void) const
{
std::vector<std::string> list;
for (auto &b: builder_)
{
list.push_back(b.first);
}
return list;
}
// factory /////////////////////////////////////////////////////////////////////
template <typename T>
std::unique_ptr<T> Factory<T>::create(const std::string type,
const std::string name) const
{
Func func;
try
{
func = builder_.at(type);
}
catch (std::out_of_range &)
{
HADRON_ERROR("object of type '" + type + "' unknown");
}
return func(name);
}
END_HADRONS_NAMESPACE
#endif // Hadrons_Factory_hpp_

View File

@ -0,0 +1,329 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/GeneticScheduler.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_GeneticScheduler_hpp_
#define Hadrons_GeneticScheduler_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Graph.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* Scheduler based on a genetic algorithm *
******************************************************************************/
template <typename T>
class GeneticScheduler
{
public:
typedef std::vector<T> Gene;
typedef std::pair<Gene *, Gene *> GenePair;
typedef std::function<int(const Gene &)> ObjFunc;
struct Parameters
{
double mutationRate;
unsigned int popSize, seed;
};
public:
// constructor
GeneticScheduler(Graph<T> &graph, const ObjFunc &func,
const Parameters &par);
// destructor
virtual ~GeneticScheduler(void) = default;
// access
const Gene & getMinSchedule(void);
int getMinValue(void);
// breed a new generation
void nextGeneration(void);
// heuristic benchmarks
void benchmarkCrossover(const unsigned int nIt);
// print population
friend std::ostream & operator<<(std::ostream &out,
const GeneticScheduler<T> &s)
{
out << "[";
for (auto &p: s.population_)
{
out << p.first << ", ";
}
out << "\b\b]";
return out;
}
private:
// evolution steps
void initPopulation(void);
void doCrossover(void);
void doMutation(void);
// genetic operators
GenePair selectPair(void);
void crossover(Gene &c1, Gene &c2, const Gene &p1, const Gene &p2);
void mutation(Gene &m, const Gene &c);
private:
Graph<T> &graph_;
const ObjFunc &func_;
const Parameters par_;
std::multimap<int, Gene> population_;
std::mt19937 gen_;
};
/******************************************************************************
* template implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
template <typename T>
GeneticScheduler<T>::GeneticScheduler(Graph<T> &graph, const ObjFunc &func,
const Parameters &par)
: graph_(graph)
, func_(func)
, par_(par)
{
gen_.seed(par_.seed);
}
// access //////////////////////////////////////////////////////////////////////
template <typename T>
const typename GeneticScheduler<T>::Gene &
GeneticScheduler<T>::getMinSchedule(void)
{
return population_.begin()->second;
}
template <typename T>
int GeneticScheduler<T>::getMinValue(void)
{
return population_.begin()->first;
}
// breed a new generation //////////////////////////////////////////////////////
template <typename T>
void GeneticScheduler<T>::nextGeneration(void)
{
// random initialization of the population if necessary
if (population_.size() != par_.popSize)
{
initPopulation();
}
LOG(Debug) << "Starting population:\n" << *this << std::endl;
// random mutations
//PARALLEL_FOR_LOOP
for (unsigned int i = 0; i < par_.popSize; ++i)
{
doMutation();
}
LOG(Debug) << "After mutations:\n" << *this << std::endl;
// mating
//PARALLEL_FOR_LOOP
for (unsigned int i = 0; i < par_.popSize/2; ++i)
{
doCrossover();
}
LOG(Debug) << "After mating:\n" << *this << std::endl;
// grim reaper
auto it = population_.begin();
std::advance(it, par_.popSize);
population_.erase(it, population_.end());
LOG(Debug) << "After grim reaper:\n" << *this << std::endl;
}
// evolution steps /////////////////////////////////////////////////////////////
template <typename T>
void GeneticScheduler<T>::initPopulation(void)
{
population_.clear();
for (unsigned int i = 0; i < par_.popSize; ++i)
{
auto p = graph_.topoSort(gen_);
population_.insert(std::make_pair(func_(p), p));
}
}
template <typename T>
void GeneticScheduler<T>::doCrossover(void)
{
auto p = selectPair();
Gene &p1 = *(p.first), &p2 = *(p.second);
Gene c1, c2;
crossover(c1, c2, p1, p2);
PARALLEL_CRITICAL
{
population_.insert(std::make_pair(func_(c1), c1));
population_.insert(std::make_pair(func_(c2), c2));
}
}
template <typename T>
void GeneticScheduler<T>::doMutation(void)
{
std::uniform_real_distribution<double> mdis(0., 1.);
std::uniform_int_distribution<unsigned int> pdis(0, population_.size() - 1);
if (mdis(gen_) < par_.mutationRate)
{
Gene m;
auto it = population_.begin();
std::advance(it, pdis(gen_));
mutation(m, it->second);
PARALLEL_CRITICAL
{
population_.insert(std::make_pair(func_(m), m));
}
}
}
// genetic operators ///////////////////////////////////////////////////////////
template <typename T>
typename GeneticScheduler<T>::GenePair GeneticScheduler<T>::selectPair(void)
{
std::vector<double> prob;
unsigned int ind;
Gene *p1, *p2;
for (auto &c: population_)
{
prob.push_back(1./c.first);
}
do
{
double probCpy;
std::discrete_distribution<unsigned int> dis1(prob.begin(), prob.end());
auto rIt = population_.begin();
ind = dis1(gen_);
std::advance(rIt, ind);
p1 = &(rIt->second);
probCpy = prob[ind];
prob[ind] = 0.;
std::discrete_distribution<unsigned int> dis2(prob.begin(), prob.end());
rIt = population_.begin();
std::advance(rIt, dis2(gen_));
p2 = &(rIt->second);
prob[ind] = probCpy;
} while (p1 == p2);
return std::make_pair(p1, p2);
}
template <typename T>
void GeneticScheduler<T>::crossover(Gene &c1, Gene &c2, const Gene &p1,
const Gene &p2)
{
Gene buf;
std::uniform_int_distribution<unsigned int> dis(0, p1.size() - 1);
unsigned int cut = dis(gen_);
c1.clear();
buf = p2;
for (unsigned int i = 0; i < cut; ++i)
{
c1.push_back(p1[i]);
buf.erase(std::find(buf.begin(), buf.end(), p1[i]));
}
for (unsigned int i = 0; i < buf.size(); ++i)
{
c1.push_back(buf[i]);
}
c2.clear();
buf = p2;
for (unsigned int i = cut; i < p1.size(); ++i)
{
buf.erase(std::find(buf.begin(), buf.end(), p1[i]));
}
for (unsigned int i = 0; i < buf.size(); ++i)
{
c2.push_back(buf[i]);
}
for (unsigned int i = cut; i < p1.size(); ++i)
{
c2.push_back(p1[i]);
}
}
template <typename T>
void GeneticScheduler<T>::mutation(Gene &m, const Gene &c)
{
Gene buf;
std::uniform_int_distribution<unsigned int> dis(0, c.size() - 1);
unsigned int cut = dis(gen_);
Graph<T> g1 = graph_, g2 = graph_;
for (unsigned int i = 0; i < cut; ++i)
{
g1.removeVertex(c[i]);
}
for (unsigned int i = cut; i < c.size(); ++i)
{
g2.removeVertex(c[i]);
}
if (g1.size() > 0)
{
buf = g1.topoSort(gen_);
}
if (g2.size() > 0)
{
m = g2.topoSort(gen_);
}
for (unsigned int i = cut; i < c.size(); ++i)
{
m.push_back(buf[i - cut]);
}
}
template <typename T>
void GeneticScheduler<T>::benchmarkCrossover(const unsigned int nIt)
{
Gene p1, p2, c1, c2;
double neg = 0., eq = 0., pos = 0., total;
int improvement;
LOG(Message) << "Benchmarking crossover..." << std::endl;
for (unsigned int i = 0; i < nIt; ++i)
{
p1 = graph_.topoSort(gen_);
p2 = graph_.topoSort(gen_);
crossover(c1, c2, p1, p2);
improvement = (func_(c1) + func_(c2) - func_(p1) - func_(p2))/2;
if (improvement < 0) neg++; else if (improvement == 0) eq++; else pos++;
}
total = neg + eq + pos;
LOG(Message) << " -: " << neg/total << " =: " << eq/total
<< " +: " << pos/total << std::endl;
}
END_HADRONS_NAMESPACE
#endif // Hadrons_GeneticScheduler_hpp_

82
extras/Hadrons/Global.cc Normal file
View File

@ -0,0 +1,82 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Global.cc
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include <Grid/Hadrons/Global.hpp>
using namespace Grid;
using namespace QCD;
using namespace Hadrons;
HadronsLogger Hadrons::HadronsLogError(1,"Error");
HadronsLogger Hadrons::HadronsLogWarning(1,"Warning");
HadronsLogger Hadrons::HadronsLogMessage(1,"Message");
HadronsLogger Hadrons::HadronsLogIterative(1,"Iterative");
HadronsLogger Hadrons::HadronsLogDebug(1,"Debug");
// pretty size formatting //////////////////////////////////////////////////////
std::string Hadrons::sizeString(long unsigned int bytes)
{
constexpr unsigned int bufSize = 256;
const char *suffixes[7] = {"", "K", "M", "G", "T", "P", "E"};
char buf[256];
long unsigned int s = 0;
double count = bytes;
while (count >= 1024 && s < 7)
{
s++;
count /= 1024;
}
if (count - floor(count) == 0.0)
{
snprintf(buf, bufSize, "%d %sB", (int)count, suffixes[s]);
}
else
{
snprintf(buf, bufSize, "%.1f %sB", count, suffixes[s]);
}
return std::string(buf);
}
// type utilities //////////////////////////////////////////////////////////////
constexpr unsigned int maxNameSize = 1024u;
std::string Hadrons::typeName(const std::type_info *info)
{
char *buf;
std::string name;
buf = abi::__cxa_demangle(info->name(), nullptr, nullptr, nullptr);
name = buf;
free(buf);
return name;
}

150
extras/Hadrons/Global.hpp Normal file
View File

@ -0,0 +1,150 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Global.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_Global_hpp_
#define Hadrons_Global_hpp_
#include <set>
#include <stack>
#include <Grid/Grid.h>
#include <cxxabi.h>
#define BEGIN_HADRONS_NAMESPACE \
namespace Grid {\
using namespace QCD;\
namespace Hadrons {\
using Grid::operator<<;
#define END_HADRONS_NAMESPACE }}
#define BEGIN_MODULE_NAMESPACE(name)\
namespace name {\
using Grid::operator<<;
#define END_MODULE_NAMESPACE }
/* the 'using Grid::operator<<;' statement prevents a very nasty compilation
* error with GCC 5 (clang & GCC 6 compile fine without it).
*/
// FIXME: find a way to do that in a more general fashion
#ifndef FIMPL
#define FIMPL WilsonImplR
#endif
BEGIN_HADRONS_NAMESPACE
// type aliases
#define TYPE_ALIASES(FImpl, suffix)\
typedef FermionOperator<FImpl> FMat##suffix; \
typedef typename FImpl::FermionField FermionField##suffix; \
typedef typename FImpl::PropagatorField PropagatorField##suffix; \
typedef typename FImpl::SitePropagator SitePropagator##suffix; \
typedef typename FImpl::DoubledGaugeField DoubledGaugeField##suffix;\
typedef std::function<void(FermionField##suffix &, \
const FermionField##suffix &)> SolverFn##suffix;
// logger
class HadronsLogger: public Logger
{
public:
HadronsLogger(int on, std::string nm): Logger("Hadrons", on, nm,
GridLogColours, "BLACK"){};
};
#define LOG(channel) std::cout << HadronsLog##channel
#define HADRON_ERROR(msg)\
LOG(Error) << msg << " (" << __FUNCTION__ << " at " << __FILE__ << ":"\
<< __LINE__ << ")" << std::endl;\
abort();
#define DEBUG_VAR(var) LOG(Debug) << #var << "= " << (var) << std::endl;
extern HadronsLogger HadronsLogError;
extern HadronsLogger HadronsLogWarning;
extern HadronsLogger HadronsLogMessage;
extern HadronsLogger HadronsLogIterative;
extern HadronsLogger HadronsLogDebug;
// singleton pattern
#define SINGLETON(name)\
public:\
name(const name &e) = delete;\
void operator=(const name &e) = delete;\
static name & getInstance(void)\
{\
static name e;\
return e;\
}\
private:\
name(void);
#define SINGLETON_DEFCTOR(name)\
public:\
name(const name &e) = delete;\
void operator=(const name &e) = delete;\
static name & getInstance(void)\
{\
static name e;\
return e;\
}\
private:\
name(void) = default;
// pretty size formating
std::string sizeString(long unsigned int bytes);
// type utilities
template <typename T>
const std::type_info * typeIdPt(const T &x)
{
return &typeid(x);
}
std::string typeName(const std::type_info *info);
template <typename T>
const std::type_info * typeIdPt(void)
{
return &typeid(T);
}
template <typename T>
std::string typeName(const T &x)
{
return typeName(typeIdPt(x));
}
template <typename T>
std::string typeName(void)
{
return typeName(typeIdPt<T>());
}
END_HADRONS_NAMESPACE
#endif // Hadrons_Global_hpp_

760
extras/Hadrons/Graph.hpp Normal file
View File

@ -0,0 +1,760 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Graph.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_Graph_hpp_
#define Hadrons_Graph_hpp_
#include <Grid/Hadrons/Global.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* Oriented graph class *
******************************************************************************/
// I/O for edges
template <typename T>
std::ostream & operator<<(std::ostream &out, const std::pair<T, T> &e)
{
out << "\"" << e.first << "\" -> \"" << e.second << "\"";
return out;
}
// main class
template <typename T>
class Graph
{
public:
typedef std::pair<T, T> Edge;
public:
// constructor
Graph(void);
// destructor
virtual ~Graph(void) = default;
// access
void addVertex(const T &value);
void addEdge(const Edge &e);
void addEdge(const T &start, const T &end);
std::vector<T> getVertices(void) const;
void removeVertex(const T &value);
void removeEdge(const Edge &e);
void removeEdge(const T &start, const T &end);
unsigned int size(void) const;
// tests
bool gotValue(const T &value) const;
// graph topological manipulations
std::vector<T> getAdjacentVertices(const T &value) const;
std::vector<T> getChildren(const T &value) const;
std::vector<T> getParents(const T &value) const;
std::vector<T> getRoots(void) const;
std::vector<Graph<T>> getConnectedComponents(void) const;
std::vector<T> topoSort(void);
template <typename Gen>
std::vector<T> topoSort(Gen &gen);
std::vector<std::vector<T>> allTopoSort(void);
// I/O
friend std::ostream & operator<<(std::ostream &out, const Graph<T> &g)
{
out << "{";
for (auto &e: g.edgeSet_)
{
out << e << ", ";
}
if (g.edgeSet_.size() != 0)
{
out << "\b\b";
}
out << "}";
return out;
}
private:
// vertex marking
void mark(const T &value, const bool doMark = true);
void markAll(const bool doMark = true);
void unmark(const T &value);
void unmarkAll(void);
bool isMarked(const T &value) const;
const T * getFirstMarked(const bool isMarked = true) const;
template <typename Gen>
const T * getRandomMarked(const bool isMarked, Gen &gen);
const T * getFirstUnmarked(void) const;
template <typename Gen>
const T * getRandomUnmarked(Gen &gen);
// prune marked/unmarked vertices
void removeMarked(const bool isMarked = true);
void removeUnmarked(void);
// depth-first search marking
void depthFirstSearch(void);
void depthFirstSearch(const T &root);
private:
std::map<T, bool> isMarked_;
std::set<Edge> edgeSet_;
};
// build depedency matrix from topological sorts
template <typename T>
std::map<T, std::map<T, bool>>
makeDependencyMatrix(const std::vector<std::vector<T>> &topSort);
/******************************************************************************
* template implementation *
******************************************************************************
* in all the following V is the number of vertex and E is the number of edge
* in the worst case E = V^2
*/
// constructor /////////////////////////////////////////////////////////////////
template <typename T>
Graph<T>::Graph(void)
{}
// access //////////////////////////////////////////////////////////////////////
// complexity: log(V)
template <typename T>
void Graph<T>::addVertex(const T &value)
{
isMarked_[value] = false;
}
// complexity: O(log(V))
template <typename T>
void Graph<T>::addEdge(const Edge &e)
{
addVertex(e.first);
addVertex(e.second);
edgeSet_.insert(e);
}
// complexity: O(log(V))
template <typename T>
void Graph<T>::addEdge(const T &start, const T &end)
{
addEdge(Edge(start, end));
}
template <typename T>
std::vector<T> Graph<T>::getVertices(void) const
{
std::vector<T> vertex;
for (auto &v: isMarked_)
{
vertex.push_back(v.first);
}
return vertex;
}
// complexity: O(V*log(V))
template <typename T>
void Graph<T>::removeVertex(const T &value)
{
// remove vertex from the mark table
auto vIt = isMarked_.find(value);
if (vIt != isMarked_.end())
{
isMarked_.erase(vIt);
}
else
{
HADRON_ERROR("vertex " << value << " does not exists");
}
// remove all edges containing the vertex
auto pred = [&value](const Edge &e)
{
return ((e.first == value) or (e.second == value));
};
auto eIt = find_if(edgeSet_.begin(), edgeSet_.end(), pred);
while (eIt != edgeSet_.end())
{
edgeSet_.erase(eIt);
eIt = find_if(edgeSet_.begin(), edgeSet_.end(), pred);
}
}
// complexity: O(log(V))
template <typename T>
void Graph<T>::removeEdge(const Edge &e)
{
auto eIt = edgeSet_.find(e);
if (eIt != edgeSet_.end())
{
edgeSet_.erase(eIt);
}
else
{
HADRON_ERROR("edge " << e << " does not exists");
}
}
// complexity: O(log(V))
template <typename T>
void Graph<T>::removeEdge(const T &start, const T &end)
{
removeEdge(Edge(start, end));
}
// complexity: O(1)
template <typename T>
unsigned int Graph<T>::size(void) const
{
return isMarked_.size();
}
// tests ///////////////////////////////////////////////////////////////////////
// complexity: O(log(V))
template <typename T>
bool Graph<T>::gotValue(const T &value) const
{
auto it = isMarked_.find(value);
if (it == isMarked_.end())
{
return false;
}
else
{
return true;
}
}
// vertex marking //////////////////////////////////////////////////////////////
// complexity: O(log(V))
template <typename T>
void Graph<T>::mark(const T &value, const bool doMark)
{
if (gotValue(value))
{
isMarked_[value] = doMark;
}
else
{
HADRON_ERROR("vertex " << value << " does not exists");
}
}
// complexity: O(V*log(V))
template <typename T>
void Graph<T>::markAll(const bool doMark)
{
for (auto &v: isMarked_)
{
mark(v.first, doMark);
}
}
// complexity: O(log(V))
template <typename T>
void Graph<T>::unmark(const T &value)
{
mark(value, false);
}
// complexity: O(V*log(V))
template <typename T>
void Graph<T>::unmarkAll(void)
{
markAll(false);
}
// complexity: O(log(V))
template <typename T>
bool Graph<T>::isMarked(const T &value) const
{
if (gotValue(value))
{
return isMarked_.at(value);
}
else
{
HADRON_ERROR("vertex " << value << " does not exists");
return false;
}
}
// complexity: O(log(V))
template <typename T>
const T * Graph<T>::getFirstMarked(const bool isMarked) const
{
auto pred = [&isMarked](const std::pair<T, bool> &v)
{
return (v.second == isMarked);
};
auto vIt = std::find_if(isMarked_.begin(), isMarked_.end(), pred);
if (vIt != isMarked_.end())
{
return &(vIt->first);
}
else
{
return nullptr;
}
}
// complexity: O(log(V))
template <typename T>
template <typename Gen>
const T * Graph<T>::getRandomMarked(const bool isMarked, Gen &gen)
{
auto pred = [&isMarked](const std::pair<T, bool> &v)
{
return (v.second == isMarked);
};
std::uniform_int_distribution<unsigned int> dis(0, size() - 1);
auto rIt = isMarked_.begin();
std::advance(rIt, dis(gen));
auto vIt = std::find_if(rIt, isMarked_.end(), pred);
if (vIt != isMarked_.end())
{
return &(vIt->first);
}
else
{
vIt = std::find_if(isMarked_.begin(), rIt, pred);
if (vIt != rIt)
{
return &(vIt->first);
}
else
{
return nullptr;
}
}
}
// complexity: O(log(V))
template <typename T>
const T * Graph<T>::getFirstUnmarked(void) const
{
return getFirstMarked(false);
}
// complexity: O(log(V))
template <typename T>
template <typename Gen>
const T * Graph<T>::getRandomUnmarked(Gen &gen)
{
return getRandomMarked(false, gen);
}
// prune marked/unmarked vertices //////////////////////////////////////////////
// complexity: O(V^2*log(V))
template <typename T>
void Graph<T>::removeMarked(const bool isMarked)
{
auto isMarkedCopy = isMarked_;
for (auto &v: isMarkedCopy)
{
if (v.second == isMarked)
{
removeVertex(v.first);
}
}
}
// complexity: O(V^2*log(V))
template <typename T>
void Graph<T>::removeUnmarked(void)
{
removeMarked(false);
}
// depth-first search marking //////////////////////////////////////////////////
// complexity: O(V*log(V))
template <typename T>
void Graph<T>::depthFirstSearch(void)
{
depthFirstSearch(isMarked_.begin()->first);
}
// complexity: O(V*log(V))
template <typename T>
void Graph<T>::depthFirstSearch(const T &root)
{
std::vector<T> adjacentVertex;
mark(root);
adjacentVertex = getAdjacentVertices(root);
for (auto &v: adjacentVertex)
{
if (!isMarked(v))
{
depthFirstSearch(v);
}
}
}
// graph topological manipulations /////////////////////////////////////////////
// complexity: O(V*log(V))
template <typename T>
std::vector<T> Graph<T>::getAdjacentVertices(const T &value) const
{
std::vector<T> adjacentVertex;
auto pred = [&value](const Edge &e)
{
return ((e.first == value) or (e.second == value));
};
auto eIt = find_if(edgeSet_.begin(), edgeSet_.end(), pred);
while (eIt != edgeSet_.end())
{
if (eIt->first == value)
{
adjacentVertex.push_back((*eIt).second);
}
else if (eIt->second == value)
{
adjacentVertex.push_back((*eIt).first);
}
eIt = find_if(++eIt, edgeSet_.end(), pred);
}
return adjacentVertex;
}
// complexity: O(V*log(V))
template <typename T>
std::vector<T> Graph<T>::getChildren(const T &value) const
{
std::vector<T> child;
auto pred = [&value](const Edge &e)
{
return (e.first == value);
};
auto eIt = find_if(edgeSet_.begin(), edgeSet_.end(), pred);
while (eIt != edgeSet_.end())
{
child.push_back((*eIt).second);
eIt = find_if(++eIt, edgeSet_.end(), pred);
}
return child;
}
// complexity: O(V*log(V))
template <typename T>
std::vector<T> Graph<T>::getParents(const T &value) const
{
std::vector<T> parent;
auto pred = [&value](const Edge &e)
{
return (e.second == value);
};
auto eIt = find_if(edgeSet_.begin(), edgeSet_.end(), pred);
while (eIt != edgeSet_.end())
{
parent.push_back((*eIt).first);
eIt = find_if(++eIt, edgeSet_.end(), pred);
}
return parent;
}
// complexity: O(V^2*log(V))
template <typename T>
std::vector<T> Graph<T>::getRoots(void) const
{
std::vector<T> root;
for (auto &v: isMarked_)
{
auto parent = getParents(v.first);
if (parent.size() == 0)
{
root.push_back(v.first);
}
}
return root;
}
// complexity: O(V^2*log(V))
template <typename T>
std::vector<Graph<T>> Graph<T>::getConnectedComponents(void) const
{
std::vector<Graph<T>> res;
Graph<T> copy(*this);
while (copy.size() > 0)
{
copy.depthFirstSearch();
res.push_back(copy);
res.back().removeUnmarked();
res.back().unmarkAll();
copy.removeMarked();
copy.unmarkAll();
}
return res;
}
// topological sort using a directed DFS algorithm
// complexity: O(V*log(V))
template <typename T>
std::vector<T> Graph<T>::topoSort(void)
{
std::stack<T> buf;
std::vector<T> res;
const T *vPt;
std::map<T, bool> tmpMarked(isMarked_);
// visit function
std::function<void(const T &)> visit = [&](const T &v)
{
if (tmpMarked.at(v))
{
HADRON_ERROR("cannot topologically sort a cyclic graph");
}
if (!isMarked(v))
{
std::vector<T> child = getChildren(v);
tmpMarked[v] = true;
for (auto &c: child)
{
visit(c);
}
mark(v);
tmpMarked[v] = false;
buf.push(v);
}
};
// reset temporary marks
for (auto &v: tmpMarked)
{
tmpMarked.at(v.first) = false;
}
// loop on unmarked vertices
unmarkAll();
vPt = getFirstUnmarked();
while (vPt)
{
visit(*vPt);
vPt = getFirstUnmarked();
}
unmarkAll();
// create result vector
while (!buf.empty())
{
res.push_back(buf.top());
buf.pop();
}
return res;
}
// random version of the topological sort
// complexity: O(V*log(V))
template <typename T>
template <typename Gen>
std::vector<T> Graph<T>::topoSort(Gen &gen)
{
std::stack<T> buf;
std::vector<T> res;
const T *vPt;
std::map<T, bool> tmpMarked(isMarked_);
// visit function
std::function<void(const T &)> visit = [&](const T &v)
{
if (tmpMarked.at(v))
{
HADRON_ERROR("cannot topologically sort a cyclic graph");
}
if (!isMarked(v))
{
std::vector<T> child = getChildren(v);
tmpMarked[v] = true;
std::shuffle(child.begin(), child.end(), gen);
for (auto &c: child)
{
visit(c);
}
mark(v);
tmpMarked[v] = false;
buf.push(v);
}
};
// reset temporary marks
for (auto &v: tmpMarked)
{
tmpMarked.at(v.first) = false;
}
// loop on unmarked vertices
unmarkAll();
vPt = getRandomUnmarked(gen);
while (vPt)
{
visit(*vPt);
vPt = getRandomUnmarked(gen);
}
unmarkAll();
// create result vector
while (!buf.empty())
{
res.push_back(buf.top());
buf.pop();
}
return res;
}
// generate all possible topological sorts
// Y. L. Varol & D. Rotem, Comput. J. 24(1), pp. 8384, 1981
// http://comjnl.oupjournals.org/cgi/doi/10.1093/comjnl/24.1.83
// complexity: O(V*log(V)) (from the paper, but really ?)
template <typename T>
std::vector<std::vector<T>> Graph<T>::allTopoSort(void)
{
std::vector<std::vector<T>> res;
std::map<T, std::map<T, bool>> iMat;
// create incidence matrix
for (auto &v1: isMarked_)
for (auto &v2: isMarked_)
{
iMat[v1.first][v2.first] = false;
}
for (auto &v: isMarked_)
{
auto cVec = getChildren(v.first);
for (auto &c: cVec)
{
iMat[v.first][c] = true;
}
}
// generate initial topological sort
res.push_back(topoSort());
// generate all other topological sorts by permutation
std::vector<T> p = res[0];
const unsigned int n = size();
std::vector<unsigned int> loc(n);
unsigned int i, k, k1;
T obj_k, obj_k1;
bool isFinal;
for (unsigned int j = 0; j < n; ++j)
{
loc[j] = j;
}
i = 0;
while (i < n-1)
{
k = loc[i];
k1 = k + 1;
obj_k = p[k];
if (k1 >= n)
{
isFinal = true;
obj_k1 = obj_k;
}
else
{
isFinal = false;
obj_k1 = p[k1];
}
if (iMat[res[0][i]][obj_k1] or isFinal)
{
for (unsigned int l = k; l >= i + 1; --l)
{
p[l] = p[l-1];
}
p[i] = obj_k;
loc[i] = i;
i++;
}
else
{
p[k] = obj_k1;
p[k1] = obj_k;
loc[i] = k1;
i = 0;
res.push_back(p);
}
}
return res;
}
// build depedency matrix from topological sorts ///////////////////////////////
// complexity: something like O(V^2*log(V!))
template <typename T>
std::map<T, std::map<T, bool>>
makeDependencyMatrix(const std::vector<std::vector<T>> &topSort)
{
std::map<T, std::map<T, bool>> m;
const std::vector<T> &vList = topSort[0];
for (auto &v1: vList)
for (auto &v2: vList)
{
bool dep = true;
for (auto &t: topSort)
{
auto i1 = std::find(t.begin(), t.end(), v1);
auto i2 = std::find(t.begin(), t.end(), v2);
dep = dep and (i1 - i2 > 0);
if (!dep) break;
}
m[v1][v2] = dep;
}
return m;
}
END_HADRONS_NAMESPACE
#endif // Hadrons_Graph_hpp_

View File

@ -0,0 +1,80 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/HadronsXmlRun.cc
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include <Grid/Hadrons/Application.hpp>
using namespace Grid;
using namespace QCD;
using namespace Hadrons;
int main(int argc, char *argv[])
{
// parse command line
std::string parameterFileName, scheduleFileName = "";
if (argc < 2)
{
std::cerr << "usage: " << argv[0] << " <parameter file> [<precomputed schedule>] [Grid options]";
std::cerr << std::endl;
std::exit(EXIT_FAILURE);
}
parameterFileName = argv[1];
if (argc > 2)
{
if (argv[2][0] != '-')
{
scheduleFileName = argv[2];
}
}
// initialization
Grid_init(&argc, &argv);
HadronsLogError.Active(GridLogError.isActive());
HadronsLogWarning.Active(GridLogWarning.isActive());
HadronsLogMessage.Active(GridLogMessage.isActive());
HadronsLogIterative.Active(GridLogIterative.isActive());
HadronsLogDebug.Active(GridLogDebug.isActive());
LOG(Message) << "Grid initialized" << std::endl;
// execution
Application application(parameterFileName);
application.parseParameterFile(parameterFileName);
if (!scheduleFileName.empty())
{
application.loadSchedule(scheduleFileName);
}
application.run();
// epilogue
LOG(Message) << "Grid is finalizing now" << std::endl;
Grid_finalize();
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,72 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/HadronsXmlSchedule.cc
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include <Grid/Hadrons/Application.hpp>
using namespace Grid;
using namespace QCD;
using namespace Hadrons;
int main(int argc, char *argv[])
{
// parse command line
std::string parameterFileName, scheduleFileName;
if (argc < 3)
{
std::cerr << "usage: " << argv[0] << " <parameter file> <schedule output> [Grid options]";
std::cerr << std::endl;
std::exit(EXIT_FAILURE);
}
parameterFileName = argv[1];
scheduleFileName = argv[2];
// initialization
Grid_init(&argc, &argv);
HadronsLogError.Active(GridLogError.isActive());
HadronsLogWarning.Active(GridLogWarning.isActive());
HadronsLogMessage.Active(GridLogMessage.isActive());
HadronsLogIterative.Active(GridLogIterative.isActive());
HadronsLogDebug.Active(GridLogDebug.isActive());
LOG(Message) << "Grid initialized" << std::endl;
// execution
Application application;
application.parseParameterFile(parameterFileName);
application.schedule();
application.printSchedule();
application.saveSchedule(scheduleFileName);
// epilogue
LOG(Message) << "Grid is finalizing now" << std::endl;
Grid_finalize();
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,29 @@
lib_LIBRARIES = libHadrons.a
bin_PROGRAMS = HadronsXmlRun HadronsXmlSchedule
include modules.inc
libHadrons_a_SOURCES = \
$(modules_cc) \
Application.cc \
Environment.cc \
Global.cc \
Module.cc
libHadrons_adir = $(pkgincludedir)/Hadrons
nobase_libHadrons_a_HEADERS = \
$(modules_hpp) \
Application.hpp \
Environment.hpp \
Factory.hpp \
GeneticScheduler.hpp \
Global.hpp \
Graph.hpp \
Module.hpp \
Modules.hpp \
ModuleFactory.hpp
HadronsXmlRun_SOURCES = HadronsXmlRun.cc
HadronsXmlRun_LDADD = libHadrons.a -lGrid
HadronsXmlSchedule_SOURCES = HadronsXmlSchedule.cc
HadronsXmlSchedule_LDADD = libHadrons.a -lGrid

71
extras/Hadrons/Module.cc Normal file
View File

@ -0,0 +1,71 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Module.cc
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include <Grid/Hadrons/Module.hpp>
using namespace Grid;
using namespace QCD;
using namespace Hadrons;
/******************************************************************************
* ModuleBase implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
ModuleBase::ModuleBase(const std::string name)
: name_(name)
, env_(Environment::getInstance())
{}
// access //////////////////////////////////////////////////////////////////////
std::string ModuleBase::getName(void) const
{
return name_;
}
Environment & ModuleBase::env(void) const
{
return env_;
}
// get factory registration name if available
std::string ModuleBase::getRegisteredName(void)
{
HADRON_ERROR("module '" + getName() + "' has a type not registered"
+ " in the factory");
}
// execution ///////////////////////////////////////////////////////////////////
void ModuleBase::operator()(void)
{
setup();
if (!env().isDryRun())
{
execute();
}
}

198
extras/Hadrons/Module.hpp Normal file
View File

@ -0,0 +1,198 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Module.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_Module_hpp_
#define Hadrons_Module_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Environment.hpp>
BEGIN_HADRONS_NAMESPACE
// module registration macros
#define MODULE_REGISTER(mod, base)\
class mod: public base\
{\
public:\
typedef base Base;\
using Base::Base;\
virtual std::string getRegisteredName(void)\
{\
return std::string(#mod);\
}\
};\
class mod##ModuleRegistrar\
{\
public:\
mod##ModuleRegistrar(void)\
{\
ModuleFactory &modFac = ModuleFactory::getInstance();\
modFac.registerBuilder(#mod, [&](const std::string name)\
{\
return std::unique_ptr<mod>(new mod(name));\
});\
}\
};\
static mod##ModuleRegistrar mod##ModuleRegistrarInstance;
#define MODULE_REGISTER_NS(mod, base, ns)\
class mod: public base\
{\
public:\
typedef base Base;\
using Base::Base;\
virtual std::string getRegisteredName(void)\
{\
return std::string(#ns "::" #mod);\
}\
};\
class ns##mod##ModuleRegistrar\
{\
public:\
ns##mod##ModuleRegistrar(void)\
{\
ModuleFactory &modFac = ModuleFactory::getInstance();\
modFac.registerBuilder(#ns "::" #mod, [&](const std::string name)\
{\
return std::unique_ptr<ns::mod>(new ns::mod(name));\
});\
}\
};\
static ns##mod##ModuleRegistrar ns##mod##ModuleRegistrarInstance;
#define ARG(...) __VA_ARGS__
/******************************************************************************
* Module class *
******************************************************************************/
// base class
class ModuleBase
{
public:
// constructor
ModuleBase(const std::string name);
// destructor
virtual ~ModuleBase(void) = default;
// access
std::string getName(void) const;
Environment &env(void) const;
// get factory registration name if available
virtual std::string getRegisteredName(void);
// dependencies/products
virtual std::vector<std::string> getInput(void) = 0;
virtual std::vector<std::string> getOutput(void) = 0;
// parse parameters
virtual void parseParameters(XmlReader &reader, const std::string name) = 0;
virtual void saveParameters(XmlWriter &writer, const std::string name) = 0;
// setup
virtual void setup(void) {};
// execution
void operator()(void);
virtual void execute(void) = 0;
private:
std::string name_;
Environment &env_;
};
// derived class, templating the parameter class
template <typename P>
class Module: public ModuleBase
{
public:
typedef P Par;
public:
// constructor
Module(const std::string name);
// destructor
virtual ~Module(void) = default;
// parse parameters
virtual void parseParameters(XmlReader &reader, const std::string name);
virtual void saveParameters(XmlWriter &writer, const std::string name);
// parameter access
const P & par(void) const;
void setPar(const P &par);
private:
P par_;
};
// no parameter type
class NoPar {};
template <>
class Module<NoPar>: public ModuleBase
{
public:
// constructor
Module(const std::string name): ModuleBase(name) {};
// destructor
virtual ~Module(void) = default;
// parse parameters (do nothing)
virtual void parseParameters(XmlReader &reader, const std::string name) {};
virtual void saveParameters(XmlWriter &writer, const std::string name)
{
push(writer, "options");
pop(writer);
};
};
/******************************************************************************
* Template implementation *
******************************************************************************/
template <typename P>
Module<P>::Module(const std::string name)
: ModuleBase(name)
{}
template <typename P>
void Module<P>::parseParameters(XmlReader &reader, const std::string name)
{
read(reader, name, par_);
}
template <typename P>
void Module<P>::saveParameters(XmlWriter &writer, const std::string name)
{
write(writer, name, par_);
}
template <typename P>
const P & Module<P>::par(void) const
{
return par_;
}
template <typename P>
void Module<P>::setPar(const P &par)
{
par_ = par;
}
END_HADRONS_NAMESPACE
#endif // Hadrons_Module_hpp_

View File

@ -1,12 +1,13 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Grid physics library, www.github.com/paboyle/Grid
Source file: ./lib/Bitwise.cc
Source file: extras/Hadrons/ModuleFactory.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Guido Cossu <guido.cossu@ed.ac.uk>
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -22,28 +23,27 @@ You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution
directory
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include <iostream>
#include <Bitwise.h>
#include <bitset>
#include <climits>
namespace Grid {
#ifndef Hadrons_ModuleFactory_hpp_
#define Hadrons_ModuleFactory_hpp_
void show_binaryrep(const unsigned char* a, size_t size) {
const unsigned char* beg = a;
const unsigned char* end = a + size;
unsigned int ctr = 0;
while (beg != end) {
std::cout << std::bitset<CHAR_BIT>(*beg++) << ' ';
ctr++;
if (ctr % GRID_REAL_BYTES == 0) std::cout << '\n';
}
std::cout << '\n';
}
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Factory.hpp>
#include <Grid/Hadrons/Module.hpp>
} // namespace
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* ModuleFactory *
******************************************************************************/
class ModuleFactory: public Factory<ModuleBase>
{
SINGLETON_DEFCTOR(ModuleFactory)
};
END_HADRONS_NAMESPACE
#endif // Hadrons_ModuleFactory_hpp_

View File

@ -0,0 +1,40 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include <Grid/Hadrons/Modules/MAction/DWF.hpp>
#include <Grid/Hadrons/Modules/MAction/Wilson.hpp>
#include <Grid/Hadrons/Modules/MContraction/Baryon.hpp>
#include <Grid/Hadrons/Modules/MContraction/Meson.hpp>
#include <Grid/Hadrons/Modules/MGauge/Load.hpp>
#include <Grid/Hadrons/Modules/MGauge/Random.hpp>
#include <Grid/Hadrons/Modules/MGauge/Unit.hpp>
#include <Grid/Hadrons/Modules/MSolver/RBPrecCG.hpp>
#include <Grid/Hadrons/Modules/MSource/Point.hpp>
#include <Grid/Hadrons/Modules/MSource/SeqGamma.hpp>
#include <Grid/Hadrons/Modules/MSource/Z2.hpp>
#include <Grid/Hadrons/Modules/Quark.hpp>

View File

@ -0,0 +1,134 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules/MAction/DWF.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_DWF_hpp_
#define Hadrons_DWF_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* Domain wall quark action *
******************************************************************************/
BEGIN_MODULE_NAMESPACE(MAction)
class DWFPar: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(DWFPar,
std::string, gauge,
unsigned int, Ls,
double , mass,
double , M5);
};
template <typename FImpl>
class TDWF: public Module<DWFPar>
{
public:
TYPE_ALIASES(FImpl,);
public:
// constructor
TDWF(const std::string name);
// destructor
virtual ~TDWF(void) = default;
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
};
MODULE_REGISTER_NS(DWF, TDWF<FIMPL>, MAction);
/******************************************************************************
* DWF template implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
template <typename FImpl>
TDWF<FImpl>::TDWF(const std::string name)
: Module<DWFPar>(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
template <typename FImpl>
std::vector<std::string> TDWF<FImpl>::getInput(void)
{
std::vector<std::string> in = {par().gauge};
return in;
}
template <typename FImpl>
std::vector<std::string> TDWF<FImpl>::getOutput(void)
{
std::vector<std::string> out = {getName()};
return out;
}
// setup ///////////////////////////////////////////////////////////////////////
template <typename FImpl>
void TDWF<FImpl>::setup(void)
{
unsigned int size;
size = 2*env().template lattice4dSize<typename FImpl::DoubledGaugeField>();
env().registerObject(getName(), size, par().Ls);
}
// execution ///////////////////////////////////////////////////////////////////
template <typename FImpl>
void TDWF<FImpl>::execute(void)
{
LOG(Message) << "Setting up domain wall fermion matrix with m= "
<< par().mass << ", M5= " << par().M5 << " and Ls= "
<< par().Ls << " using gauge field '" << par().gauge << "'"
<< std::endl;
env().createGrid(par().Ls);
auto &U = *env().template getObject<LatticeGaugeField>(par().gauge);
auto &g4 = *env().getGrid();
auto &grb4 = *env().getRbGrid();
auto &g5 = *env().getGrid(par().Ls);
auto &grb5 = *env().getRbGrid(par().Ls);
FMat *fMatPt = new DomainWallFermion<FImpl>(U, g5, grb5, g4, grb4,
par().mass, par().M5);
env().setObject(getName(), fMatPt);
}
END_MODULE_NAMESPACE
END_HADRONS_NAMESPACE
#endif // Hadrons_DWF_hpp_

View File

@ -0,0 +1,126 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules/MAction/Wilson.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_Wilson_hpp_
#define Hadrons_Wilson_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* TWilson quark action *
******************************************************************************/
BEGIN_MODULE_NAMESPACE(MAction)
class WilsonPar: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(WilsonPar,
std::string, gauge,
double , mass);
};
template <typename FImpl>
class TWilson: public Module<WilsonPar>
{
public:
TYPE_ALIASES(FImpl,);
public:
// constructor
TWilson(const std::string name);
// destructor
virtual ~TWilson(void) = default;
// dependencies/products
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
};
MODULE_REGISTER_NS(Wilson, TWilson<FIMPL>, MAction);
/******************************************************************************
* TWilson template implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
template <typename FImpl>
TWilson<FImpl>::TWilson(const std::string name)
: Module<WilsonPar>(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
template <typename FImpl>
std::vector<std::string> TWilson<FImpl>::getInput(void)
{
std::vector<std::string> in = {par().gauge};
return in;
}
template <typename FImpl>
std::vector<std::string> TWilson<FImpl>::getOutput(void)
{
std::vector<std::string> out = {getName()};
return out;
}
// setup ///////////////////////////////////////////////////////////////////////
template <typename FImpl>
void TWilson<FImpl>::setup(void)
{
unsigned int size;
size = 2*env().template lattice4dSize<typename FImpl::DoubledGaugeField>();
env().registerObject(getName(), size);
}
// execution ///////////////////////////////////////////////////////////////////
template <typename FImpl>
void TWilson<FImpl>::execute()
{
LOG(Message) << "Setting up TWilson fermion matrix with m= " << par().mass
<< " using gauge field '" << par().gauge << "'" << std::endl;
auto &U = *env().template getObject<LatticeGaugeField>(par().gauge);
auto &grid = *env().getGrid();
auto &gridRb = *env().getRbGrid();
FMat *fMatPt = new WilsonFermion<FImpl>(U, grid, gridRb, par().mass);
env().setObject(getName(), fMatPt);
}
END_MODULE_NAMESPACE
END_HADRONS_NAMESPACE
#endif // Hadrons_Wilson_hpp_

View File

@ -0,0 +1,131 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules/MContraction/Baryon.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_Baryon_hpp_
#define Hadrons_Baryon_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* Baryon *
******************************************************************************/
BEGIN_MODULE_NAMESPACE(MContraction)
class BaryonPar: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(BaryonPar,
std::string, q1,
std::string, q2,
std::string, q3,
std::string, output);
};
template <typename FImpl1, typename FImpl2, typename FImpl3>
class TBaryon: public Module<BaryonPar>
{
public:
TYPE_ALIASES(FImpl1, 1);
TYPE_ALIASES(FImpl2, 2);
TYPE_ALIASES(FImpl3, 3);
class Result: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(Result,
std::vector<std::vector<std::vector<Complex>>>, corr);
};
public:
// constructor
TBaryon(const std::string name);
// destructor
virtual ~TBaryon(void) = default;
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// execution
virtual void execute(void);
};
MODULE_REGISTER_NS(Baryon, ARG(TBaryon<FIMPL, FIMPL, FIMPL>), MContraction);
/******************************************************************************
* TBaryon implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
template <typename FImpl1, typename FImpl2, typename FImpl3>
TBaryon<FImpl1, FImpl2, FImpl3>::TBaryon(const std::string name)
: Module<BaryonPar>(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
template <typename FImpl1, typename FImpl2, typename FImpl3>
std::vector<std::string> TBaryon<FImpl1, FImpl2, FImpl3>::getInput(void)
{
std::vector<std::string> input = {par().q1, par().q2, par().q3};
return input;
}
template <typename FImpl1, typename FImpl2, typename FImpl3>
std::vector<std::string> TBaryon<FImpl1, FImpl2, FImpl3>::getOutput(void)
{
std::vector<std::string> out = {getName()};
return out;
}
// execution ///////////////////////////////////////////////////////////////////
template <typename FImpl1, typename FImpl2, typename FImpl3>
void TBaryon<FImpl1, FImpl2, FImpl3>::execute(void)
{
LOG(Message) << "Computing baryon contractions '" << getName() << "' using"
<< " quarks '" << par().q1 << "', '" << par().q2 << "', and '"
<< par().q3 << "'" << std::endl;
XmlWriter writer(par().output);
PropagatorField1 &q1 = *env().template getObject<PropagatorField1>(par().q1);
PropagatorField2 &q2 = *env().template getObject<PropagatorField2>(par().q2);
PropagatorField3 &q3 = *env().template getObject<PropagatorField3>(par().q2);
LatticeComplex c(env().getGrid());
Result result;
// FIXME: do contractions
write(writer, "meson", result);
}
END_MODULE_NAMESPACE
END_HADRONS_NAMESPACE
#endif // Hadrons_Baryon_hpp_

View File

@ -0,0 +1,137 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules/MContraction/Meson.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_Meson_hpp_
#define Hadrons_Meson_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* TMeson *
******************************************************************************/
BEGIN_MODULE_NAMESPACE(MContraction)
class MesonPar: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(MesonPar,
std::string, q1,
std::string, q2,
std::string, output,
Gamma::Algebra, gammaSource,
Gamma::Algebra, gammaSink);
};
template <typename FImpl1, typename FImpl2>
class TMeson: public Module<MesonPar>
{
public:
TYPE_ALIASES(FImpl1, 1);
TYPE_ALIASES(FImpl2, 2);
class Result: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(Result, std::vector<Complex>, corr);
};
public:
// constructor
TMeson(const std::string name);
// destructor
virtual ~TMeson(void) = default;
// dependencies/products
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// execution
virtual void execute(void);
};
MODULE_REGISTER_NS(Meson, ARG(TMeson<FIMPL, FIMPL>), MContraction);
/******************************************************************************
* TMeson implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
template <typename FImpl1, typename FImpl2>
TMeson<FImpl1, FImpl2>::TMeson(const std::string name)
: Module<MesonPar>(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
template <typename FImpl1, typename FImpl2>
std::vector<std::string> TMeson<FImpl1, FImpl2>::getInput(void)
{
std::vector<std::string> input = {par().q1, par().q2};
return input;
}
template <typename FImpl1, typename FImpl2>
std::vector<std::string> TMeson<FImpl1, FImpl2>::getOutput(void)
{
std::vector<std::string> output = {getName()};
return output;
}
// execution ///////////////////////////////////////////////////////////////////
template <typename FImpl1, typename FImpl2>
void TMeson<FImpl1, FImpl2>::execute(void)
{
LOG(Message) << "Computing meson contractions '" << getName() << "' using"
<< " quarks '" << par().q1 << "' and '" << par().q2 << "'"
<< std::endl;
XmlWriter writer(par().output);
PropagatorField1 &q1 = *env().template getObject<PropagatorField1>(par().q1);
PropagatorField2 &q2 = *env().template getObject<PropagatorField2>(par().q2);
LatticeComplex c(env().getGrid());
Gamma gSrc(par().gammaSource), gSnk(par().gammaSink);
Gamma g5(Gamma::Algebra::Gamma5);
std::vector<TComplex> buf;
Result result;
c = trace(gSnk*q1*adj(gSrc)*g5*adj(q2)*g5);
sliceSum(c, buf, Tp);
result.corr.resize(buf.size());
for (unsigned int t = 0; t < buf.size(); ++t)
{
result.corr[t] = TensorRemove(buf[t]);
}
write(writer, "meson", result);
}
END_MODULE_NAMESPACE
END_HADRONS_NAMESPACE
#endif // Hadrons_Meson_hpp_

View File

@ -0,0 +1,78 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules/MGauge/Load.cc
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include <Grid/Hadrons/Modules/MGauge/Load.hpp>
using namespace Grid;
using namespace Hadrons;
using namespace MGauge;
/******************************************************************************
* TLoad implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
TLoad::TLoad(const std::string name)
: Module<LoadPar>(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
std::vector<std::string> TLoad::getInput(void)
{
std::vector<std::string> in;
return in;
}
std::vector<std::string> TLoad::getOutput(void)
{
std::vector<std::string> out = {getName()};
return out;
}
// setup ///////////////////////////////////////////////////////////////////////
void TLoad::setup(void)
{
env().registerLattice<LatticeGaugeField>(getName());
}
// execution ///////////////////////////////////////////////////////////////////
void TLoad::execute(void)
{
NerscField header;
std::string fileName = par().file + "."
+ std::to_string(env().getTrajectory());
LOG(Message) << "Loading NERSC configuration from file '" << fileName
<< "'" << std::endl;
LatticeGaugeField &U = *env().createLattice<LatticeGaugeField>(getName());
NerscIO::readConfiguration(U, header, fileName);
LOG(Message) << "NERSC header:" << std::endl;
dump_nersc_header(header, LOG(Message));
}

View File

@ -0,0 +1,73 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules/MGauge/Load.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_Load_hpp_
#define Hadrons_Load_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* Load a NERSC configuration *
******************************************************************************/
BEGIN_MODULE_NAMESPACE(MGauge)
class LoadPar: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(LoadPar,
std::string, file);
};
class TLoad: public Module<LoadPar>
{
public:
// constructor
TLoad(const std::string name);
// destructor
virtual ~TLoad(void) = default;
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
};
MODULE_REGISTER_NS(Load, TLoad, MGauge);
END_MODULE_NAMESPACE
END_HADRONS_NAMESPACE
#endif // Hadrons_Load_hpp_

View File

@ -0,0 +1,69 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules/MGauge/Random.cc
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include <Grid/Hadrons/Modules/MGauge/Random.hpp>
using namespace Grid;
using namespace Hadrons;
using namespace MGauge;
/******************************************************************************
* TRandom implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
TRandom::TRandom(const std::string name)
: Module<NoPar>(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
std::vector<std::string> TRandom::getInput(void)
{
return std::vector<std::string>();
}
std::vector<std::string> TRandom::getOutput(void)
{
std::vector<std::string> out = {getName()};
return out;
}
// setup ///////////////////////////////////////////////////////////////////////
void TRandom::setup(void)
{
env().registerLattice<LatticeGaugeField>(getName());
}
// execution ///////////////////////////////////////////////////////////////////
void TRandom::execute(void)
{
LOG(Message) << "Generating random gauge configuration" << std::endl;
LatticeGaugeField &U = *env().createLattice<LatticeGaugeField>(getName());
SU3::HotConfiguration(*env().get4dRng(), U);
}

View File

@ -0,0 +1,66 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules/MGauge/Random.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_Random_hpp_
#define Hadrons_Random_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* Random gauge *
******************************************************************************/
BEGIN_MODULE_NAMESPACE(MGauge)
class TRandom: public Module<NoPar>
{
public:
// constructor
TRandom(const std::string name);
// destructor
virtual ~TRandom(void) = default;
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
};
MODULE_REGISTER_NS(Random, TRandom, MGauge);
END_MODULE_NAMESPACE
END_HADRONS_NAMESPACE
#endif // Hadrons_Random_hpp_

View File

@ -0,0 +1,69 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules/MGauge/Unit.cc
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include <Grid/Hadrons/Modules/MGauge/Unit.hpp>
using namespace Grid;
using namespace Hadrons;
using namespace MGauge;
/******************************************************************************
* TUnit implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
TUnit::TUnit(const std::string name)
: Module<NoPar>(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
std::vector<std::string> TUnit::getInput(void)
{
return std::vector<std::string>();
}
std::vector<std::string> TUnit::getOutput(void)
{
std::vector<std::string> out = {getName()};
return out;
}
// setup ///////////////////////////////////////////////////////////////////////
void TUnit::setup(void)
{
env().registerLattice<LatticeGaugeField>(getName());
}
// execution ///////////////////////////////////////////////////////////////////
void TUnit::execute(void)
{
LOG(Message) << "Creating unit gauge configuration" << std::endl;
LatticeGaugeField &U = *env().createLattice<LatticeGaugeField>(getName());
SU3::ColdConfiguration(*env().get4dRng(), U);
}

View File

@ -0,0 +1,66 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules/MGauge/Unit.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_Unit_hpp_
#define Hadrons_Unit_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* Unit gauge *
******************************************************************************/
BEGIN_MODULE_NAMESPACE(MGauge)
class TUnit: public Module<NoPar>
{
public:
// constructor
TUnit(const std::string name);
// destructor
virtual ~TUnit(void) = default;
// dependencies/products
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
};
MODULE_REGISTER_NS(Unit, TUnit, MGauge);
END_MODULE_NAMESPACE
END_HADRONS_NAMESPACE
#endif // Hadrons_Unit_hpp_

View File

@ -0,0 +1,132 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules/MSolver/RBPrecCG.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_RBPrecCG_hpp_
#define Hadrons_RBPrecCG_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* Schur red-black preconditioned CG *
******************************************************************************/
BEGIN_MODULE_NAMESPACE(MSolver)
class RBPrecCGPar: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(RBPrecCGPar,
std::string, action,
double , residual);
};
template <typename FImpl>
class TRBPrecCG: public Module<RBPrecCGPar>
{
public:
TYPE_ALIASES(FImpl,);
public:
// constructor
TRBPrecCG(const std::string name);
// destructor
virtual ~TRBPrecCG(void) = default;
// dependencies/products
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
};
MODULE_REGISTER_NS(RBPrecCG, TRBPrecCG<FIMPL>, MSolver);
/******************************************************************************
* TRBPrecCG template implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
template <typename FImpl>
TRBPrecCG<FImpl>::TRBPrecCG(const std::string name)
: Module(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
template <typename FImpl>
std::vector<std::string> TRBPrecCG<FImpl>::getInput(void)
{
std::vector<std::string> in = {par().action};
return in;
}
template <typename FImpl>
std::vector<std::string> TRBPrecCG<FImpl>::getOutput(void)
{
std::vector<std::string> out = {getName()};
return out;
}
// setup ///////////////////////////////////////////////////////////////////////
template <typename FImpl>
void TRBPrecCG<FImpl>::setup(void)
{
auto Ls = env().getObjectLs(par().action);
env().registerObject(getName(), 0, Ls);
env().addOwnership(getName(), par().action);
}
// execution ///////////////////////////////////////////////////////////////////
template <typename FImpl>
void TRBPrecCG<FImpl>::execute(void)
{
auto &mat = *(env().template getObject<FMat>(par().action));
auto solver = [&mat, this](FermionField &sol, const FermionField &source)
{
ConjugateGradient<FermionField> cg(par().residual, 10000);
SchurRedBlackDiagMooeeSolve<FermionField> schurSolver(cg);
schurSolver(mat, source, sol);
};
LOG(Message) << "setting up Schur red-black preconditioned CG for"
<< " action '" << par().action << "' with residual "
<< par().residual << std::endl;
env().setObject(getName(), new SolverFn(solver));
}
END_MODULE_NAMESPACE
END_HADRONS_NAMESPACE
#endif // Hadrons_RBPrecCG_hpp_

View File

@ -0,0 +1,135 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules/MSource/Point.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_Point_hpp_
#define Hadrons_Point_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/*
Point source
------------
* src_x = delta_x,position
* options:
- position: space-separated integer sequence (e.g. "0 1 1 0")
*/
/******************************************************************************
* TPoint *
******************************************************************************/
BEGIN_MODULE_NAMESPACE(MSource)
class PointPar: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(PointPar,
std::string, position);
};
template <typename FImpl>
class TPoint: public Module<PointPar>
{
public:
TYPE_ALIASES(FImpl,);
public:
// constructor
TPoint(const std::string name);
// destructor
virtual ~TPoint(void) = default;
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
};
MODULE_REGISTER_NS(Point, TPoint<FIMPL>, MSource);
/******************************************************************************
* TPoint template implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
template <typename FImpl>
TPoint<FImpl>::TPoint(const std::string name)
: Module<PointPar>(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
template <typename FImpl>
std::vector<std::string> TPoint<FImpl>::getInput(void)
{
std::vector<std::string> in;
return in;
}
template <typename FImpl>
std::vector<std::string> TPoint<FImpl>::getOutput(void)
{
std::vector<std::string> out = {getName()};
return out;
}
// setup ///////////////////////////////////////////////////////////////////////
template <typename FImpl>
void TPoint<FImpl>::setup(void)
{
env().template registerLattice<PropagatorField>(getName());
}
// execution ///////////////////////////////////////////////////////////////////
template <typename FImpl>
void TPoint<FImpl>::execute(void)
{
std::vector<int> position = strToVec<int>(par().position);
typename SitePropagator::scalar_object id;
LOG(Message) << "Creating point source at position [" << par().position
<< "]" << std::endl;
PropagatorField &src = *env().template createLattice<PropagatorField>(getName());
id = 1.;
src = zero;
pokeSite(id, src, position);
}
END_MODULE_NAMESPACE
END_HADRONS_NAMESPACE
#endif // Hadrons_Point_hpp_

View File

@ -0,0 +1,163 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules/MSource/SeqGamma.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_SeqGamma_hpp_
#define Hadrons_SeqGamma_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/*
Sequential source
-----------------------------
* src_x = q_x * theta(x_3 - tA) * theta(tB - x_3) * gamma * exp(i x.mom)
* options:
- q: input propagator (string)
- tA: begin timeslice (integer)
- tB: end timesilce (integer)
- gamma: gamma product to insert (integer)
- mom: momentum insertion, space-separated float sequence (e.g ".1 .2 1. 0.")
*/
/******************************************************************************
* SeqGamma *
******************************************************************************/
BEGIN_MODULE_NAMESPACE(MSource)
class SeqGammaPar: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(SeqGammaPar,
std::string, q,
unsigned int, tA,
unsigned int, tB,
Gamma::Algebra, gamma,
std::string, mom);
};
template <typename FImpl>
class TSeqGamma: public Module<SeqGammaPar>
{
public:
TYPE_ALIASES(FImpl,);
public:
// constructor
TSeqGamma(const std::string name);
// destructor
virtual ~TSeqGamma(void) = default;
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
};
MODULE_REGISTER_NS(SeqGamma, TSeqGamma<FIMPL>, MSource);
/******************************************************************************
* TSeqGamma implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
template <typename FImpl>
TSeqGamma<FImpl>::TSeqGamma(const std::string name)
: Module<SeqGammaPar>(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
template <typename FImpl>
std::vector<std::string> TSeqGamma<FImpl>::getInput(void)
{
std::vector<std::string> in = {par().q};
return in;
}
template <typename FImpl>
std::vector<std::string> TSeqGamma<FImpl>::getOutput(void)
{
std::vector<std::string> out = {getName()};
return out;
}
// setup ///////////////////////////////////////////////////////////////////////
template <typename FImpl>
void TSeqGamma<FImpl>::setup(void)
{
env().template registerLattice<PropagatorField>(getName());
}
// execution ///////////////////////////////////////////////////////////////////
template <typename FImpl>
void TSeqGamma<FImpl>::execute(void)
{
if (par().tA == par().tB)
{
LOG(Message) << "Generating gamma_" << par().gamma
<< " sequential source at t= " << par().tA << std::endl;
}
else
{
LOG(Message) << "Generating gamma_" << par().gamma
<< " sequential source for "
<< par().tA << " <= t <= " << par().tB << std::endl;
}
PropagatorField &src = *env().template createLattice<PropagatorField>(getName());
PropagatorField &q = *env().template getObject<PropagatorField>(par().q);
Lattice<iScalar<vInteger>> t(env().getGrid());
LatticeComplex ph(env().getGrid()), coor(env().getGrid());
Gamma g(par().gamma);
std::vector<Real> p;
Complex i(0.0,1.0);
p = strToVec<Real>(par().mom);
ph = zero;
for(unsigned int mu = 0; mu < env().getNd(); mu++)
{
LatticeCoordinate(coor, mu);
ph = ph + p[mu]*coor;
}
ph = exp(i*ph);
LatticeCoordinate(t, Tp);
src = where((t >= par().tA) and (t <= par().tB), ph*(g*q), 0.*q);
}
END_MODULE_NAMESPACE
END_HADRONS_NAMESPACE
#endif // Hadrons_SeqGamma_hpp_

View File

@ -0,0 +1,151 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules/MSource/Z2.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_Z2_hpp_
#define Hadrons_Z2_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/*
Z_2 stochastic source
-----------------------------
* src_x = eta_x * theta(x_3 - tA) * theta(tB - x_3)
the eta_x are independent uniform random numbers in {+/- 1 +/- i}
* options:
- tA: begin timeslice (integer)
- tB: end timesilce (integer)
*/
/******************************************************************************
* Z2 stochastic source *
******************************************************************************/
BEGIN_MODULE_NAMESPACE(MSource)
class Z2Par: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(Z2Par,
unsigned int, tA,
unsigned int, tB);
};
template <typename FImpl>
class TZ2: public Module<Z2Par>
{
public:
TYPE_ALIASES(FImpl,);
public:
// constructor
TZ2(const std::string name);
// destructor
virtual ~TZ2(void) = default;
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
};
MODULE_REGISTER_NS(Z2, TZ2<FIMPL>, MSource);
/******************************************************************************
* TZ2 template implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
template <typename FImpl>
TZ2<FImpl>::TZ2(const std::string name)
: Module<Z2Par>(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
template <typename FImpl>
std::vector<std::string> TZ2<FImpl>::getInput(void)
{
std::vector<std::string> in;
return in;
}
template <typename FImpl>
std::vector<std::string> TZ2<FImpl>::getOutput(void)
{
std::vector<std::string> out = {getName()};
return out;
}
// setup ///////////////////////////////////////////////////////////////////////
template <typename FImpl>
void TZ2<FImpl>::setup(void)
{
env().template registerLattice<PropagatorField>(getName());
}
// execution ///////////////////////////////////////////////////////////////////
template <typename FImpl>
void TZ2<FImpl>::execute(void)
{
Lattice<iScalar<vInteger>> t(env().getGrid());
LatticeComplex eta(env().getGrid());
Complex shift(1., 1.);
if (par().tA == par().tB)
{
LOG(Message) << "Generating Z_2 wall source at t= " << par().tA
<< std::endl;
}
else
{
LOG(Message) << "Generating Z_2 band for " << par().tA << " <= t <= "
<< par().tB << std::endl;
}
PropagatorField &src = *env().template createLattice<PropagatorField>(getName());
LatticeCoordinate(t, Tp);
bernoulli(*env().get4dRng(), eta);
eta = (2.*eta - shift)*(1./::sqrt(2.));
eta = where((t >= par().tA) and (t <= par().tB), eta, 0.*eta);
src = 1.;
src = src*eta;
}
END_MODULE_NAMESPACE
END_HADRONS_NAMESPACE
#endif // Hadrons_Z2_hpp_

View File

@ -0,0 +1,185 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: extras/Hadrons/Modules/Quark.hpp
Copyright (C) 2015
Copyright (C) 2016
Author: Antonin Portelli <antonin.portelli@me.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef Hadrons_Quark_hpp_
#define Hadrons_Quark_hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* TQuark *
******************************************************************************/
class QuarkPar: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(QuarkPar,
std::string, source,
std::string, solver);
};
template <typename FImpl>
class TQuark: public Module<QuarkPar>
{
public:
TYPE_ALIASES(FImpl,);
public:
// constructor
TQuark(const std::string name);
// destructor
virtual ~TQuark(void) = default;
// dependencies/products
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
private:
unsigned int Ls_;
SolverFn *solver_{nullptr};
};
MODULE_REGISTER(Quark, TQuark<FIMPL>);
/******************************************************************************
* TQuark implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
template <typename FImpl>
TQuark<FImpl>::TQuark(const std::string name)
: Module(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
template <typename FImpl>
std::vector<std::string> TQuark<FImpl>::getInput(void)
{
std::vector<std::string> in = {par().source, par().solver};
return in;
}
template <typename FImpl>
std::vector<std::string> TQuark<FImpl>::getOutput(void)
{
std::vector<std::string> out = {getName(), getName() + "_5d"};
return out;
}
// setup ///////////////////////////////////////////////////////////////////////
template <typename FImpl>
void TQuark<FImpl>::setup(void)
{
Ls_ = env().getObjectLs(par().solver);
env().template registerLattice<PropagatorField>(getName());
if (Ls_ > 1)
{
env().template registerLattice<PropagatorField>(getName() + "_5d", Ls_);
}
}
// execution ///////////////////////////////////////////////////////////////////
template <typename FImpl>
void TQuark<FImpl>::execute(void)
{
LOG(Message) << "Computing quark propagator '" << getName() << "'"
<< std::endl;
FermionField source(env().getGrid(Ls_)), sol(env().getGrid(Ls_)),
tmp(env().getGrid());
std::string propName = (Ls_ == 1) ? getName() : (getName() + "_5d");
PropagatorField &prop = *env().template createLattice<PropagatorField>(propName);
PropagatorField &fullSrc = *env().template getObject<PropagatorField>(par().source);
SolverFn &solver = *env().template getObject<SolverFn>(par().solver);
if (Ls_ > 1)
{
env().template createLattice<PropagatorField>(getName());
}
LOG(Message) << "Inverting using solver '" << par().solver
<< "' on source '" << par().source << "'" << std::endl;
for (unsigned int s = 0; s < Ns; ++s)
for (unsigned int c = 0; c < Nc; ++c)
{
LOG(Message) << "Inversion for spin= " << s << ", color= " << c
<< std::endl;
// source conversion for 4D sources
if (!env().isObject5d(par().source))
{
if (Ls_ == 1)
{
PropToFerm(source, fullSrc, s, c);
}
else
{
source = zero;
PropToFerm(tmp, fullSrc, s, c);
InsertSlice(tmp, source, 0, 0);
InsertSlice(tmp, source, Ls_-1, 0);
axpby_ssp_pplus(source, 0., source, 1., source, 0, 0);
axpby_ssp_pminus(source, 0., source, 1., source, Ls_-1, Ls_-1);
}
}
// source conversion for 5D sources
else
{
if (Ls_ != env().getObjectLs(par().source))
{
HADRON_ERROR("Ls mismatch between quark action and source");
}
else
{
PropToFerm(source, fullSrc, s, c);
}
}
sol = zero;
solver(sol, source);
FermToProp(prop, sol, s, c);
// create 4D propagators from 5D one if necessary
if (Ls_ > 1)
{
PropagatorField &p4d =
*env().template getObject<PropagatorField>(getName());
axpby_ssp_pminus(sol, 0., sol, 1., sol, 0, 0);
axpby_ssp_pplus(sol, 0., sol, 1., sol, 0, Ls_-1);
ExtractSlice(tmp, sol, 0, 0);
FermToProp(p4d, tmp, s, c);
}
}
}
END_HADRONS_NAMESPACE
#endif // Hadrons_Quark_hpp_

View File

@ -0,0 +1,39 @@
#include <Grid/Hadrons/Modules/___FILEBASENAME___.hpp>
using namespace Grid;
using namespace Hadrons;
/******************************************************************************
* T___FILEBASENAME___ implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
T___FILEBASENAME___::T___FILEBASENAME___(const std::string name)
: Module<___FILEBASENAME___Par>(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
std::vector<std::string> T___FILEBASENAME___::getInput(void)
{
std::vector<std::string> in;
return in;
}
std::vector<std::string> T___FILEBASENAME___::getOutput(void)
{
std::vector<std::string> out = {getName()};
return out;
}
// setup ///////////////////////////////////////////////////////////////////////
void T___FILEBASENAME___::setup(void)
{
}
// execution ///////////////////////////////////////////////////////////////////
void T___FILEBASENAME___::execute(void)
{
}

View File

@ -0,0 +1,40 @@
#ifndef Hadrons____FILEBASENAME____hpp_
#define Hadrons____FILEBASENAME____hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* ___FILEBASENAME___ *
******************************************************************************/
class ___FILEBASENAME___Par: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(___FILEBASENAME___Par,
unsigned int, i);
};
class T___FILEBASENAME___: public Module<___FILEBASENAME___Par>
{
public:
// constructor
T___FILEBASENAME___(const std::string name);
// destructor
virtual ~T___FILEBASENAME___(void) = default;
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
};
MODULE_REGISTER(___FILEBASENAME___, T___FILEBASENAME___);
END_HADRONS_NAMESPACE
#endif // Hadrons____FILEBASENAME____hpp_

View File

@ -0,0 +1,40 @@
#include <Grid/Hadrons/Modules/___NAMESPACE___/___FILEBASENAME___.hpp>
using namespace Grid;
using namespace Hadrons;
using namespace ___NAMESPACE___;
/******************************************************************************
* T___FILEBASENAME___ implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
T___FILEBASENAME___::T___FILEBASENAME___(const std::string name)
: Module<___FILEBASENAME___Par>(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
std::vector<std::string> T___FILEBASENAME___::getInput(void)
{
std::vector<std::string> in;
return in;
}
std::vector<std::string> T___FILEBASENAME___::getOutput(void)
{
std::vector<std::string> out = {getName()};
return out;
}
// setup ///////////////////////////////////////////////////////////////////////
void T___FILEBASENAME___::setup(void)
{
}
// execution ///////////////////////////////////////////////////////////////////
void T___FILEBASENAME___::execute(void)
{
}

View File

@ -0,0 +1,44 @@
#ifndef Hadrons____FILEBASENAME____hpp_
#define Hadrons____FILEBASENAME____hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* ___FILEBASENAME___ *
******************************************************************************/
BEGIN_MODULE_NAMESPACE(___NAMESPACE___)
class ___FILEBASENAME___Par: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(___FILEBASENAME___Par,
unsigned int, i);
};
class T___FILEBASENAME___: public Module<___FILEBASENAME___Par>
{
public:
// constructor
T___FILEBASENAME___(const std::string name);
// destructor
virtual ~T___FILEBASENAME___(void) = default;
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
};
MODULE_REGISTER_NS(___FILEBASENAME___, T___FILEBASENAME___, ___NAMESPACE___);
END_MODULE_NAMESPACE
END_HADRONS_NAMESPACE
#endif // Hadrons____FILEBASENAME____hpp_

View File

@ -0,0 +1,81 @@
#ifndef Hadrons____FILEBASENAME____hpp_
#define Hadrons____FILEBASENAME____hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* ___FILEBASENAME___ *
******************************************************************************/
class ___FILEBASENAME___Par: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(___FILEBASENAME___Par,
unsigned int, i);
};
template <typename FImpl>
class T___FILEBASENAME___: public Module<___FILEBASENAME___Par>
{
public:
// constructor
T___FILEBASENAME___(const std::string name);
// destructor
virtual ~T___FILEBASENAME___(void) = default;
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
};
MODULE_REGISTER(___FILEBASENAME___, T___FILEBASENAME___<FIMPL>);
/******************************************************************************
* T___FILEBASENAME___ implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
template <typename FImpl>
T___FILEBASENAME___<FImpl>::T___FILEBASENAME___(const std::string name)
: Module<___FILEBASENAME___Par>(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
template <typename FImpl>
std::vector<std::string> T___FILEBASENAME___<FImpl>::getInput(void)
{
std::vector<std::string> in;
return in;
}
template <typename FImpl>
std::vector<std::string> T___FILEBASENAME___<FImpl>::getOutput(void)
{
std::vector<std::string> out = {getName()};
return out;
}
// setup ///////////////////////////////////////////////////////////////////////
template <typename FImpl>
void T___FILEBASENAME___<FImpl>::setup(void)
{
}
// execution ///////////////////////////////////////////////////////////////////
template <typename FImpl>
void T___FILEBASENAME___<FImpl>::execute(void)
{
}
END_HADRONS_NAMESPACE
#endif // Hadrons____FILEBASENAME____hpp_

View File

@ -0,0 +1,85 @@
#ifndef Hadrons____FILEBASENAME____hpp_
#define Hadrons____FILEBASENAME____hpp_
#include <Grid/Hadrons/Global.hpp>
#include <Grid/Hadrons/Module.hpp>
#include <Grid/Hadrons/ModuleFactory.hpp>
BEGIN_HADRONS_NAMESPACE
/******************************************************************************
* ___FILEBASENAME___ *
******************************************************************************/
BEGIN_MODULE_NAMESPACE(___NAMESPACE___)
class ___FILEBASENAME___Par: Serializable
{
public:
GRID_SERIALIZABLE_CLASS_MEMBERS(___FILEBASENAME___Par,
unsigned int, i);
};
template <typename FImpl>
class T___FILEBASENAME___: public Module<___FILEBASENAME___Par>
{
public:
// constructor
T___FILEBASENAME___(const std::string name);
// destructor
virtual ~T___FILEBASENAME___(void) = default;
// dependency relation
virtual std::vector<std::string> getInput(void);
virtual std::vector<std::string> getOutput(void);
// setup
virtual void setup(void);
// execution
virtual void execute(void);
};
MODULE_REGISTER_NS(___FILEBASENAME___, T___FILEBASENAME___<FIMPL>, ___NAMESPACE___);
/******************************************************************************
* T___FILEBASENAME___ implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
template <typename FImpl>
T___FILEBASENAME___<FImpl>::T___FILEBASENAME___(const std::string name)
: Module<___FILEBASENAME___Par>(name)
{}
// dependencies/products ///////////////////////////////////////////////////////
template <typename FImpl>
std::vector<std::string> T___FILEBASENAME___<FImpl>::getInput(void)
{
std::vector<std::string> in;
return in;
}
template <typename FImpl>
std::vector<std::string> T___FILEBASENAME___<FImpl>::getOutput(void)
{
std::vector<std::string> out = {getName()};
return out;
}
// setup ///////////////////////////////////////////////////////////////////////
template <typename FImpl>
void T___FILEBASENAME___<FImpl>::setup(void)
{
}
// execution ///////////////////////////////////////////////////////////////////
template <typename FImpl>
void T___FILEBASENAME___<FImpl>::execute(void)
{
}
END_MODULE_NAMESPACE
END_HADRONS_NAMESPACE
#endif // Hadrons____FILEBASENAME____hpp_

31
extras/Hadrons/add_module.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
if (( $# != 1 && $# != 2)); then
echo "usage: `basename $0` <module name> [<namespace>]" 1>&2
exit 1
fi
NAME=$1
NS=$2
if (( $# == 1 )); then
if [ -e "Modules/${NAME}.cc" ] || [ -e "Modules/${NAME}.hpp" ]; then
echo "error: files Modules/${NAME}.* already exists" 1>&2
exit 1
fi
sed "s/___FILEBASENAME___/${NAME}/g" Modules/templates/Module.cc.template > Modules/${NAME}.cc
sed "s/___FILEBASENAME___/${NAME}/g" Modules/templates/Module.hpp.template > Modules/${NAME}.hpp
elif (( $# == 2 )); then
mkdir -p Modules/${NS}
if [ -e "Modules/${NS}/${NAME}.cc" ] || [ -e "Modules/${NS}/${NAME}.hpp" ]; then
echo "error: files Modules/${NS}/${NAME}.* already exists" 1>&2
exit 1
fi
TMPCC=".${NS}.${NAME}.tmp.cc"
TMPHPP=".${NS}.${NAME}.tmp.hpp"
sed "s/___FILEBASENAME___/${NAME}/g" Modules/templates/Module_in_NS.cc.template > ${TMPCC}
sed "s/___FILEBASENAME___/${NAME}/g" Modules/templates/Module_in_NS.hpp.template > ${TMPHPP}
sed "s/___NAMESPACE___/${NS}/g" ${TMPCC} > Modules/${NS}/${NAME}.cc
sed "s/___NAMESPACE___/${NS}/g" ${TMPHPP} > Modules/${NS}/${NAME}.hpp
rm -f ${TMPCC} ${TMPHPP}
fi
./make_module_list.sh

View File

@ -0,0 +1,28 @@
#!/usr/bin/env bash
if (( $# != 1 && $# != 2)); then
echo "usage: `basename $0` <module name> [<namespace>]" 1>&2
exit 1
fi
NAME=$1
NS=$2
if (( $# == 1 )); then
if [ -e "Modules/${NAME}.cc" ] || [ -e "Modules/${NAME}.hpp" ]; then
echo "error: files Modules/${NAME}.* already exists" 1>&2
exit 1
fi
sed "s/___FILEBASENAME___/${NAME}/g" Modules/templates/Module_tmp.hpp.template > Modules/${NAME}.hpp
elif (( $# == 2 )); then
mkdir -p Modules/${NS}
if [ -e "Modules/${NS}/${NAME}.cc" ] || [ -e "Modules/${NS}/${NAME}.hpp" ]; then
echo "error: files Modules/${NS}/${NAME}.* already exists" 1>&2
exit 1
fi
TMPCC=".${NS}.${NAME}.tmp.cc"
TMPHPP=".${NS}.${NAME}.tmp.hpp"
sed "s/___FILEBASENAME___/${NAME}/g" Modules/templates/Module_tmp_in_NS.hpp.template > ${TMPHPP}
sed "s/___NAMESPACE___/${NS}/g" ${TMPHPP} > Modules/${NS}/${NAME}.hpp
rm -f ${TMPCC} ${TMPHPP}
fi
./make_module_list.sh

View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
echo 'modules_cc =\' > modules.inc
find Modules -name '*.cc' -type f -print | sed 's/^/ /;$q;s/$/ \\/' >> modules.inc
echo '' >> modules.inc
echo 'modules_hpp =\' >> modules.inc
find Modules -name '*.hpp' -type f -print | sed 's/^/ /;$q;s/$/ \\/' >> modules.inc
echo '' >> modules.inc
rm -f Modules.hpp
for f in `find Modules -name '*.hpp'`; do
echo "#include <Grid/Hadrons/${f}>" >> Modules.hpp
done

View File

@ -0,0 +1,19 @@
modules_cc =\
Modules/MGauge/Load.cc \
Modules/MGauge/Random.cc \
Modules/MGauge/Unit.cc
modules_hpp =\
Modules/MAction/DWF.hpp \
Modules/MAction/Wilson.hpp \
Modules/MContraction/Baryon.hpp \
Modules/MContraction/Meson.hpp \
Modules/MGauge/Load.hpp \
Modules/MGauge/Random.hpp \
Modules/MGauge/Unit.hpp \
Modules/MSolver/RBPrecCG.hpp \
Modules/MSource/Point.hpp \
Modules/MSource/SeqGamma.hpp \
Modules/MSource/Z2.hpp \
Modules/Quark.hpp

1
extras/Makefile.am Normal file
View File

@ -0,0 +1 @@
SUBDIRS = Hadrons

View File

@ -39,6 +39,7 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
#include <Grid/algorithms/approx/MultiShiftFunction.h>
#include <Grid/algorithms/iterative/ConjugateGradient.h>
#include <Grid/algorithms/iterative/ConjugateGradientShifted.h>
#include <Grid/algorithms/iterative/ConjugateResidual.h>
#include <Grid/algorithms/iterative/NormalEquations.h>
#include <Grid/algorithms/iterative/SchurRedBlack.h>

65
lib/AlignedAllocator.cc Normal file
View File

@ -0,0 +1,65 @@
#include <Grid/Grid.h>
namespace Grid {
int PointerCache::victim;
PointerCache::PointerCacheEntry PointerCache::Entries[PointerCache::Ncache];
void *PointerCache::Insert(void *ptr,size_t bytes) {
if (bytes < 4096 ) return NULL;
#ifdef _OPENMP
assert(omp_in_parallel()==0);
#endif
void * ret = NULL;
int v = -1;
for(int e=0;e<Ncache;e++) {
if ( Entries[e].valid==0 ) {
v=e;
break;
}
}
if ( v==-1 ) {
v=victim;
victim = (victim+1)%Ncache;
}
if ( Entries[v].valid ) {
ret = Entries[v].address;
Entries[v].valid = 0;
Entries[v].address = NULL;
Entries[v].bytes = 0;
}
Entries[v].address=ptr;
Entries[v].bytes =bytes;
Entries[v].valid =1;
return ret;
}
void *PointerCache::Lookup(size_t bytes) {
if (bytes < 4096 ) return NULL;
#ifdef _OPENMP
assert(omp_in_parallel()==0);
#endif
for(int e=0;e<Ncache;e++){
if ( Entries[e].valid && ( Entries[e].bytes == bytes ) ) {
Entries[e].valid = 0;
return Entries[e].address;
}
}
return NULL;
}
}

View File

@ -1,4 +1,4 @@
/*************************************************************************************
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
@ -42,9 +42,32 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
namespace Grid {
class PointerCache {
private:
static const int Ncache=8;
static int victim;
typedef struct {
void *address;
size_t bytes;
int valid;
} PointerCacheEntry;
static PointerCacheEntry Entries[Ncache];
public:
static void *Insert(void *ptr,size_t bytes) ;
static void *Lookup(size_t bytes) ;
};
////////////////////////////////////////////////////////////////////
// A lattice of something, but assume the something is SIMDized.
////////////////////////////////////////////////////////////////////
template<typename _Tp>
class alignedAllocator {
public:
@ -66,27 +89,27 @@ public:
pointer allocate(size_type __n, const void* _p= 0)
{
size_type bytes = __n*sizeof(_Tp);
_Tp *ptr = (_Tp *) PointerCache::Lookup(bytes);
#ifdef HAVE_MM_MALLOC_H
_Tp * ptr = (_Tp *) _mm_malloc(__n*sizeof(_Tp),128);
if ( ptr == (_Tp *) NULL ) ptr = (_Tp *) _mm_malloc(bytes,128);
#else
_Tp * ptr = (_Tp *) memalign(128,__n*sizeof(_Tp));
if ( ptr == (_Tp *) NULL ) ptr = (_Tp *) memalign(128,bytes);
#endif
_Tp tmp;
#ifdef GRID_NUMA
#pragma omp parallel for schedule(static)
for(int i=0;i<__n;i++){
ptr[i]=tmp;
}
#endif
return ptr;
}
void deallocate(pointer __p, size_type) {
void deallocate(pointer __p, size_type __n) {
size_type bytes = __n * sizeof(_Tp);
pointer __freeme = (pointer)PointerCache::Insert((void *)__p,bytes);
#ifdef HAVE_MM_MALLOC_H
_mm_free((void *)__p);
if ( __freeme ) _mm_free((void *)__freeme);
#else
free((void *)__p);
if ( __freeme ) free((void *)__freeme);
#endif
}
void construct(pointer __p, const _Tp& __val) { };

View File

@ -1,76 +0,0 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: ./lib/Bitwise.h
Copyright (C) 2016
Author: Guido Cossu <guido.cossu@ed.ac.uk>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution
directory
*************************************************************************************/
/* END LEGAL */
#ifndef GRID_BITWISE_H
#define GRID_BITWISE_H
#include <cassert>
#include <cfloat>
#include <bitset>
#include <climits>
#include <Config.h>
#ifdef GRID_DEFAULT_PRECISION_SINGLE
#define GRID_REAL_BYTES 4
#endif
#ifdef GRID_DEFAULT_PRECISION_DOUBLE
#define GRID_REAL_BYTES 8
#endif
namespace Grid {
void show_binaryrep(const unsigned char* a, size_t size);
template <typename T>
void show_binaryrep(const T& a) {
const char* beg = reinterpret_cast<const char*>(&a);
const char* end = beg + sizeof(a);
unsigned int ctr = 0;
while (beg != end) {
std::cout << std::bitset<CHAR_BIT>(*beg++) << ' ';
ctr++;
if (ctr % GRID_REAL_BYTES == 0) std::cout << '\n';
}
std::cout << '\n';
}
template <typename T>
void bitwise_xor(T& l, T& r, unsigned char* xors) {
assert(sizeof(l) == sizeof(r));
unsigned char* org = reinterpret_cast<unsigned char*>(&l);
unsigned char* cur = reinterpret_cast<unsigned char*>(&r);
int words = sizeof(l) / sizeof(*org);
unsigned char result = 0;
for (int w = 0; w < words; w++) xors[w] = (org[w] ^ cur[w]);
}
}; // namespace
#endif

View File

@ -59,14 +59,13 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
///////////////////
// Grid headers
///////////////////
#include <Grid/serialisation/Serialisation.h>
#include "Config.h"
#include <Grid/Timer.h>
#include <Grid/Bitwise.h>
#include <Grid/PerfCount.h>
#include <Grid/Log.h>
#include <Grid/AlignedAllocator.h>
#include <Grid/Simd.h>
#include <Grid/serialisation/Serialisation.h>
#include <Grid/Threads.h>
#include <Grid/Lexicographic.h>
#include <Grid/Init.h>

1
lib/Hadrons Symbolic link
View File

@ -0,0 +1 @@
../extras/Hadrons

View File

@ -41,7 +41,7 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
#include <signal.h>
#include <iostream>
#include <iterator>
#include <Grid.h>
#include <Grid/Grid.h>
#include <algorithm>
#include <iterator>
#include <cstdlib>

View File

@ -29,7 +29,7 @@ See the full license in the file "LICENSE" in the top level distribution
directory
*************************************************************************************/
/* END LEGAL */
#include <Grid.h>
#include <Grid/Grid.h>
#include <cxxabi.h>
@ -100,7 +100,7 @@ void Grid_quiesce_nodes(void) {
me = shmem_my_pe();
#endif
if (me) {
std::cout.setstate(std::ios::badbit);// mute all nodes except 0
std::cout.setstate(std::ios::badbit);
}
}

View File

@ -110,8 +110,8 @@ public:
friend std::ostream& operator<< (std::ostream& stream, Logger& log){
if ( log.active ) {
stream << log.background()<< log.topName << log.background()<< " : ";
stream << log.colour() <<std::setw(14) << std::left << log.name << log.background() << " : ";
stream << log.background()<< std::setw(10) << std::left << log.topName << log.background()<< " : ";
stream << log.colour() << std::setw(14) << std::left << log.name << log.background() << " : ";
if ( log.timestamp ) {
StopWatch.Stop();
GridTime now = StopWatch.Elapsed();

View File

@ -1,4 +1,5 @@
extra_sources=
extra_headers=
if BUILD_COMMS_MPI
extra_sources+=communicator/Communicator_mpi.cc
extra_sources+=communicator/Communicator_base.cc
@ -24,6 +25,12 @@ if BUILD_COMMS_NONE
extra_sources+=communicator/Communicator_base.cc
endif
if BUILD_HDF5
extra_sources+=serialisation/Hdf5IO.cc
extra_headers+=serialisation/Hdf5IO.h
extra_headers+=serialisation/Hdf5Type.h
endif
#
# Libraries
#
@ -32,6 +39,9 @@ include Eigen.inc
lib_LIBRARIES = libGrid.a
libGrid_a_SOURCES = $(CCFILES) $(extra_sources)
CCFILES += $(extra_sources)
HFILES += $(extra_headers)
libGrid_a_SOURCES = $(CCFILES)
libGrid_adir = $(pkgincludedir)
nobase_dist_pkginclude_HEADERS = $(HFILES) $(eigen_files) Config.h

View File

@ -26,8 +26,8 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
*************************************************************************************/
/* END LEGAL */
#include <Grid.h>
#include <PerfCount.h>
#include <Grid/Grid.h>
#include <Grid/PerfCount.h>
namespace Grid {

View File

@ -205,12 +205,13 @@ public:
void Stop(void) {
count=0;
cycles=0;
size_t ign;
#ifdef __linux__
if ( fd!= -1) {
::ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
::ioctl(cyclefd, PERF_EVENT_IOC_DISABLE, 0);
::read(fd, &count, sizeof(long long));
::read(cyclefd, &cycles, sizeof(long long));
ign=::read(fd, &count, sizeof(long long));
ign=::read(cyclefd, &cycles, sizeof(long long));
}
elapsed = cyclecount() - begin;
#else

View File

@ -1,6 +1,6 @@
#include <Grid.h>
#include <PerfCount.h>
#include <Stat.h>
#include <Grid/Grid.h>
#include <Grid/PerfCount.h>
#include <Grid/Stat.h>
namespace Grid {

View File

@ -113,7 +113,7 @@ Gather_plane_simple_table (std::vector<std::pair<int,int> >& table,const Lattice
{
PARALLEL_FOR_LOOP
for(int i=0;i<table.size();i++){
buffer[off+table[i].first]=compress(rhs._odata[so+table[i].second]);
vstream(buffer[off+table[i].first],compress(rhs._odata[so+table[i].second]));
}
}

View File

@ -38,21 +38,21 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
#ifdef GRID_OMP
#include <omp.h>
#ifdef GRID_NUMA
#define PARALLEL_FOR_LOOP _Pragma("omp parallel for schedule(static)")
#define PARALLEL_FOR_LOOP_INTERN _Pragma("omp for schedule(static)")
#else
#define PARALLEL_FOR_LOOP _Pragma("omp parallel for schedule(runtime)")
#define PARALLEL_FOR_LOOP_INTERN _Pragma("omp for schedule(runtime)")
#define PARALLEL_FOR_LOOP _Pragma("omp parallel for schedule(static)")
#define PARALLEL_FOR_LOOP_INTERN _Pragma("omp for schedule(static)")
#else
#define PARALLEL_FOR_LOOP _Pragma("omp parallel for schedule(runtime)")
#define PARALLEL_FOR_LOOP_INTERN _Pragma("omp for schedule(runtime)")
#endif
#define PARALLEL_NESTED_LOOP2 _Pragma("omp parallel for collapse(2)")
#define PARALLEL_REGION _Pragma("omp parallel")
#define PARALLEL_FOR_LOOP_STATIC _Pragma("omp parallel for schedule(static)")
#define PARALLEL_NESTED_LOOP2 _Pragma("omp parallel for collapse(2)")
#define PARALLEL_REGION _Pragma("omp parallel")
#define PARALLEL_CRITICAL _Pragma("omp critical")
#else
#define PARALLEL_FOR_LOOP
#define PARALLEL_FOR_LOOP_INTERN
#define PARALLEL_NESTED_LOOP2
#define PARALLEL_REGION
#define PARALLEL_FOR_LOOP_STATIC
#define PARALLEL_CRITICAL
#endif
namespace Grid {

View File

@ -25,7 +25,7 @@ Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include <Grid.h>
#include <Grid/Grid.h>
namespace Grid {
double MultiShiftFunction::approx(double x)

View File

@ -20,7 +20,7 @@
#include<iomanip>
#include<cassert>
#include<algorithms/approx/Remez.h>
#include<Grid/algorithms/approx/Remez.h>
// Constructor
AlgRemez::AlgRemez(double lower, double upper, long precision)

View File

@ -9,7 +9,6 @@ Copyright (C) 2015
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
Author: paboyle <paboyle@ph.ed.ac.uk>
Author: Guido Cossu <guido.cossu@ed.ac.uk>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -34,21 +33,6 @@ directory
namespace Grid {
struct CG_state {
bool do_repro;
std::vector<RealD> residuals;
CG_state() {reset();}
void reset(){
do_repro = false;
residuals.clear();
}
};
enum CGexec_mode{ Default, ReproducibilityTest };
/////////////////////////////////////////////////////////////
// Base classes for iterative processes based on operators
// single input vec, single output vec.
@ -61,30 +45,10 @@ class ConjugateGradient : public OperatorFunction<Field> {
// Defaults true.
RealD Tolerance;
Integer MaxIterations;
// Reproducibility controls
bool ReproTest;
CG_state CGState; //to check reproducibility by repeating the CG
ReproducibilityState<typename Field::vector_object> ReprTest; // for the inner proucts
// Constructor
ConjugateGradient(RealD tol, Integer maxit, CGexec_mode Mode = Default)
: Tolerance(tol),MaxIterations(maxit){
switch(Mode)
{
case Default :
ErrorOnNoConverge = true;
ReproTest = false;
case ReproducibilityTest :
ErrorOnNoConverge = false;
ReproTest = true;
}
};
void set_reproducibility_interval(unsigned int interval){
ReprTest.interval = interval;
}
ConjugateGradient(RealD tol, Integer maxit, bool err_on_no_conv = true)
: Tolerance(tol),
MaxIterations(maxit),
ErrorOnNoConverge(err_on_no_conv){};
void operator()(LinearOperatorBase<Field> &Linop, const Field &src,
Field &psi) {
@ -96,37 +60,34 @@ class ConjugateGradient : public OperatorFunction<Field> {
Field p(src);
Field mmp(src);
Field r(src);
Field psi_start(psi);// save for the repro test
if (CGState.do_repro && ReproTest)
std::cout << GridLogMessage << "Starting reproducibility test, full check every "
<< ReprTest.interval << " calls" << std::endl;
if(!ReprTest.do_check)
ReprTest.reset();
ReprTest.enable_reprocheck=ReproTest;
// Initial residual computation & set up
RealD guess = norm2(psi, ReprTest);
RealD guess = norm2(psi);
assert(std::isnan(guess) == 0);
Linop.HermOpAndNorm(psi, mmp, d, b);// eventually split this for the norm check
Linop.HermOpAndNorm(psi, mmp, d, b);
r = src - mmp;
p = r;
a = norm2(p, ReprTest);
a = norm2(p);
cp = a;
ssq = norm2(src, ReprTest);
ssq = norm2(src);
std::cout << GridLogIterative << "ConjugateGradient: guess " << guess << std::endl;
std::cout << GridLogIterative << "ConjugateGradient: src " << ssq << std::endl;
std::cout << GridLogIterative << "ConjugateGradient: mp " << d << std::endl;
std::cout << GridLogIterative << "ConjugateGradient: mmp " << b << std::endl;
std::cout << GridLogIterative << "ConjugateGradient: cp,r " << cp << std::endl;
std::cout << GridLogIterative << "ConjugateGradient: p " << a << std::endl;
std::cout << GridLogIterative << std::setprecision(4)
<< "ConjugateGradient: guess " << guess << std::endl;
std::cout << GridLogIterative << std::setprecision(4)
<< "ConjugateGradient: src " << ssq << std::endl;
std::cout << GridLogIterative << std::setprecision(4)
<< "ConjugateGradient: mp " << d << std::endl;
std::cout << GridLogIterative << std::setprecision(4)
<< "ConjugateGradient: mmp " << b << std::endl;
std::cout << GridLogIterative << std::setprecision(4)
<< "ConjugateGradient: cp,r " << cp << std::endl;
std::cout << GridLogIterative << std::setprecision(4)
<< "ConjugateGradient: p " << a << std::endl;
RealD rsq = Tolerance * Tolerance * ssq;
@ -146,10 +107,10 @@ class ConjugateGradient : public OperatorFunction<Field> {
SolverTimer.Start();
int k;
for (k = 1; k <= MaxIterations; k++) {
c = cp;// old residual
c = cp;
MatrixTimer.Start();
Linop.HermOpAndNorm(p, mmp, d, qq);// mmp = Ap, d=pAp
Linop.HermOpAndNorm(p, mmp, d, qq);
MatrixTimer.Stop();
LinalgTimer.Start();
@ -157,31 +118,14 @@ class ConjugateGradient : public OperatorFunction<Field> {
// ComplexD dck = innerProduct(p,mmp);
a = c / d;
b_pred = a * (a * qq - d) / c;// a check
b_pred = a * (a * qq - d) / c;
axpy(r, -a, mmp, r);// new residual r = r_old - a * Ap
cp = norm2(r, ReprTest); // bookkeeping this norm
if (ReproTest && !CGState.do_repro) {
CGState.residuals.push_back(cp); // save residuals state
std::cout << GridLogIterative << "ReproTest: Saving state" << std::endl;
}
if (ReproTest && CGState.do_repro){
// check that the residual agrees with the previous run
std::cout << GridLogIterative << "ReproTest: Checking state k=" << k << std::endl;
if (cp != CGState.residuals[k-1]){
std::cout << GridLogMessage << "Failing reproducibility test";
std::cout << GridLogMessage << " at k=" << k << std::endl;
std::cout << GridLogMessage << "saved residual = " << CGState.residuals[k-1]
<< " cp = " << cp << std::endl;
exit(1); // exit after the first failure
}
}
cp = axpy_norm(r, -a, mmp, r);
b = cp / c;
// Fuse these loops ; should be really easy
psi = a * p + psi; // update solution
p = p * b + r; // update search direction
psi = a * p + psi;
p = p * b + r;
LinalgTimer.Stop();
std::cout << GridLogIterative << "ConjugateGradient: Iteration " << k
@ -212,22 +156,6 @@ class ConjugateGradient : public OperatorFunction<Field> {
if (ErrorOnNoConverge) assert(true_residual / Tolerance < 10000.0);
if (! (CGState.do_repro && ReproTest)){
CGState.do_repro = true;
ReprTest.do_check = true;
ReprTest.reset_counter();
this->operator()(Linop, src, psi_start);// run the repro test
if (ReprTest.success)
std::cout << GridLogMessage << "Reproducibility test passed" << std::endl;
else{
std::cout << GridLogMessage << "Reproducibility test failed" << std::endl;
exit(1);
}
}
// Clear state
CGState.reset();
ReprTest.reset();
return;
}
}

View File

@ -55,6 +55,9 @@ namespace Grid {
}
void operator() (const FieldD &src_d_in, FieldD &sol_d){
(*this)(src_d_in,sol_d,NULL);
}
void operator() (const FieldD &src_d_in, FieldD &sol_d, RealD *shift){
GridStopWatch TotalTimer;
TotalTimer.Start();
@ -82,7 +85,7 @@ namespace Grid {
FieldF sol_f(SinglePrecGrid);
sol_f.checkerboard = cb;
ConjugateGradient<FieldF> CG_f(inner_tol, MaxInnerIterations);
ConjugateGradientShifted<FieldF> CG_f(inner_tol, MaxInnerIterations);
CG_f.ErrorOnNoConverge = false;
GridStopWatch InnerCGtimer;
@ -92,6 +95,7 @@ namespace Grid {
for(Integer outer_iter = 0; outer_iter < MaxOuterIterations; outer_iter++){
//Compute double precision rsd and also new RHS vector.
Linop_d.HermOp(sol_d, tmp_d);
if(shift) axpy(tmp_d,*shift,sol_d,tmp_d);
RealD norm = axpy_norm(src_d, -1., tmp_d, src_d_in); //src_d is residual vector
std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradient: Outer iteration " <<outer_iter<<" residual "<< norm<< " target "<< stop<<std::endl;
@ -115,7 +119,7 @@ namespace Grid {
//Inner CG
CG_f.Tolerance = inner_tol;
InnerCGtimer.Start();
CG_f(Linop_f, src_f, sol_f);
CG_f(Linop_f, src_f, sol_f,shift);
InnerCGtimer.Stop();
//Convert sol back to double and add to double prec solution
@ -129,8 +133,8 @@ namespace Grid {
//Final trial CG
std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradient: Starting final patch-up double-precision solve"<<std::endl;
ConjugateGradient<FieldD> CG_d(Tolerance, MaxInnerIterations);
CG_d(Linop_d, src_d_in, sol_d);
ConjugateGradientShifted<FieldD> CG_d(Tolerance, MaxInnerIterations);
CG_d(Linop_d, src_d_in, sol_d,shift);
TotalTimer.Stop();
std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradient: Total " << TotalTimer.Elapsed() << " Precision change " << PrecChangeTimer.Elapsed() << " Inner CG total " << InnerCGtimer.Elapsed() << std::endl;

View File

@ -45,6 +45,7 @@ public:
Integer MaxIterations;
int verbose;
MultiShiftFunction shifts;
int iter;
ConjugateGradientMultiShift(Integer maxit,MultiShiftFunction &_shifts) :
MaxIterations(maxit),
@ -60,6 +61,7 @@ void operator() (LinearOperatorBase<Field> &Linop, const Field &src, Field &psi)
std::vector<Field> results(nshift,grid);
(*this)(Linop,src,results,psi);
}
void operator() (LinearOperatorBase<Field> &Linop, const Field &src, std::vector<Field> &results, Field &psi)
{
int nshift = shifts.order;
@ -105,11 +107,12 @@ void operator() (LinearOperatorBase<Field> &Linop, const Field &src, std::vector
RealD a,b,c,d;
RealD cp,bp,qq; //prev
int cb=src.checkerboard;
// Matrix mult fields
Field r(grid);
Field p(grid);
Field p(grid); p.checkerboard = src.checkerboard;
Field tmp(grid);
Field mmp(grid);
Field mmp(grid);mmp.checkerboard = src.checkerboard;
// Check lightest mass
for(int s=0;s<nshift;s++){
@ -132,6 +135,9 @@ void operator() (LinearOperatorBase<Field> &Linop, const Field &src, std::vector
p=src;
//MdagM+m[0]
std::cout << "p.checkerboard " << p.checkerboard
<< "mmp.checkerboard " << mmp.checkerboard << std::endl;
Linop.HermOpAndNorm(p,mmp,d,qq);
axpy(mmp,mass[0],p,mmp);
RealD rn = norm2(p);
@ -269,6 +275,7 @@ void operator() (LinearOperatorBase<Field> &Linop, const Field &src, std::vector
RealD cn = norm2(src);
std::cout<<GridLogMessage<<"CGMultiShift: shift["<<s<<"] true residual "<<std::sqrt(rn/cn)<<std::endl;
}
iter = k;
return;
}
}

View File

@ -0,0 +1,404 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: ./lib/algorithms/iterative/ConjugateGradientMultiShiftMixedPrec.h
Copyright (C) 2015
Author: Chulwoo Jung <chulwoo@quark.phy.bnl.gov>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END/ LEGAL */
#ifndef GRID_CONJUGATE_GRADIENT_MULTI_MIXED_PREC_H
#define GRID_CONJUGATE_GRADIENT_MULTI_MIXED_PREC_H
namespace Grid {
//Mixed precision restarted defect correction CG
template<class FieldD,class FieldF
//, typename std::enable_if< getPrecision<FieldD>::value == 2, int>::type = 0
//, typename std::enable_if< getPrecision<FieldF>::value == 1, int>::type = 0
>
class MixedPrecisionConjugateGradientMultiShift : public LinearFunction<FieldD> {
public:
// RealD Tolerance;
Integer MaxInnerIterations;
Integer MaxOuterIterations;
GridBase* SinglePrecGrid; //Grid for single-precision fields
RealD OuterLoopNormMult; //Stop the outer loop and move to a final double prec solve when the residual is OuterLoopNormMult * Tolerance
LinearOperatorBase<FieldF> &Linop_f;
LinearOperatorBase<FieldD> &Linop_d;
MultiShiftFunction shifts;
Integer iter;
//Option to speed up *inner single precision* solves using a LinearFunction that produces a guess
// LinearFunction<FieldF> *guesser;
MixedPrecisionConjugateGradientMultiShift(GridBase* _sp_grid, LinearOperatorBase<FieldF> &_Linop_f, LinearOperatorBase<FieldD> &_Linop_d,
Integer maxinnerit, MultiShiftFunction &_shifts ) :
Linop_f(_Linop_f), Linop_d(_Linop_d),
MaxInnerIterations(maxinnerit), SinglePrecGrid(_sp_grid),
OuterLoopNormMult(100.), shifts(_shifts) {};
void operator() (const FieldD &src_d_in, FieldD &sol_d){
assert(0); // not yet implemented
}
void operator() (const FieldD &src_d_in, std::vector<FieldD> &sol_d){
GridStopWatch TotalTimer;
TotalTimer.Start();
int cb = src_d_in.checkerboard;
int nshift = shifts.order;
assert(nshift == sol_d.size());
for(int i=0;i<nshift;i++) sol_d[i].checkerboard = cb;
RealD src_norm = norm2(src_d_in);
// RealD stop = src_norm * Tolerance*Tolerance;
GridBase* DoublePrecGrid = src_d_in._grid;
FieldD tmp_d(DoublePrecGrid); tmp_d.checkerboard = cb;
FieldD tmp2_d(DoublePrecGrid); tmp2_d.checkerboard = cb;
FieldD src_d(DoublePrecGrid);
src_d = src_d_in; //source for next inner iteration, computed from residual during operation
// RealD inner_tol = Tolerance;
FieldD psi_d(DoublePrecGrid);psi_d.checkerboard = cb;
FieldF src_f(SinglePrecGrid);
src_f.checkerboard = cb;
std::vector<FieldF> sol_f(nshift,SinglePrecGrid);
for(int i=0;i<nshift;i++) sol_f[i].checkerboard = cb;
// ConjugateGradientShifted<FieldF> CG_f(inner_tol, MaxInnerIterations);
ConjugateGradientMultiShift<FieldF> MSCG(MaxInnerIterations,shifts);
// CG_f.ErrorOnNoConverge = false;
GridStopWatch InnerCGtimer;
GridStopWatch PrecChangeTimer;
{
// std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradient: Outer iteration " <<outer_iter<<" residual "<< norm<< " target "<< stop<<std::endl;
// if(norm < OuterLoopNormMult * stop){
// std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradient: Outer iteration converged on iteration " <<outer_iter <<std::endl;
// break;
// }
// while(norm * inner_tol * inner_tol < stop) inner_tol *= 2; // inner_tol = sqrt(stop/norm) ??
PrecChangeTimer.Start();
precisionChange(src_f, src_d);
PrecChangeTimer.Stop();
// zeroit(sol_f);
//Inner CG
InnerCGtimer.Start();
int if_relup = 0;
#if 0
MSCG(Linop_f,src_f,sol_f);
#else
{
GridBase *grid = SinglePrecGrid;
////////////////////////////////////////////////////////////////////////
// Convenience references to the info stored in "MultiShiftFunction"
////////////////////////////////////////////////////////////////////////
int nshift = shifts.order;
std::vector<RealD> &mass(shifts.poles); // Make references to array in "shifts"
std::vector<RealD> &mresidual(shifts.tolerances);
std::vector<RealD> alpha(nshift,1.);
std::vector<FieldF> ps(nshift,grid);// Search directions
assert(sol_f.size()==nshift);
assert(mass.size()==nshift);
assert(mresidual.size()==nshift);
// dynamic sized arrays on stack; 2d is a pain with vector
RealD bs[nshift];
RealD rsq[nshift];
RealD z[nshift][2];
int converged[nshift];
const int primary =0;
//Primary shift fields CG iteration
RealD a,b,c,d;
RealD cp,bp,qq; //prev
int cb=src_f.checkerboard;
// Matrix mult fields
FieldF r(grid); r.checkerboard = src_f.checkerboard;
FieldF p(grid); p.checkerboard = src_f.checkerboard;
FieldF tmp(grid); tmp.checkerboard = src_f.checkerboard;
FieldF mmp(grid);mmp.checkerboard = src_f.checkerboard;
FieldF psi(grid);psi.checkerboard = src_f.checkerboard;
std::cout.precision(12);
std::cout<<GridLogMessage<<"norm2(psi_d)= "<<norm2(psi_d)<<std::endl;
std::cout<<GridLogMessage<<"norm2(psi)= "<<norm2(psi)<<std::endl;
// Check lightest mass
for(int s=0;s<nshift;s++){
assert( mass[s]>= mass[primary] );
converged[s]=0;
}
// Wire guess to zero
// Residuals "r" are src
// First search direction "p" is also src
cp = norm2(src_f);
Real c_relup = cp;
for(int s=0;s<nshift;s++){
rsq[s] = cp * mresidual[s] * mresidual[s];
std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradientMultiShift: shift "<<s
<<" target resid "<<rsq[s]<<std::endl;
ps[s] = src_f;
}
// r and p for primary
r=src_f;
p=src_f;
//MdagM+m[0]
std::cout << "p.checkerboard " << p.checkerboard
<< "mmp.checkerboard " << mmp.checkerboard << std::endl;
Linop_f.HermOpAndNorm(p,mmp,d,qq);
axpy(mmp,mass[0],p,mmp);
RealD rn = norm2(p);
d += rn*mass[0];
// have verified that inner product of
// p and mmp is equal to d after this since
// the d computation is tricky
// qq = real(innerProduct(p,mmp));
// std::cout<<GridLogMessage << "debug equal ? qq "<<qq<<" d "<< d<<std::endl;
b = -cp /d;
// Set up the various shift variables
int iz=0;
z[0][1-iz] = 1.0;
z[0][iz] = 1.0;
bs[0] = b;
for(int s=1;s<nshift;s++){
z[s][1-iz] = 1.0;
z[s][iz] = 1.0/( 1.0 - b*(mass[s]-mass[0]));
bs[s] = b*z[s][iz];
}
// r += b[0] A.p[0]
// c= norm(r)
c=axpy_norm(r,b,mmp,r);
axpby(psi,0.,-bs[0],src_f,src_f);
for(int s=0;s<nshift;s++) {
axpby(sol_f[s],0.,-bs[s]*alpha[s],src_f,src_f);
}
// Iteration loop
int k;
// inefficient zeroing, please replace!
// RealD sol_norm = axpy_norm(sol_d[0],-1.,sol_d[0],sol_d[0]);
zeroit(sol_d[0]);
std::cout<<GridLogMessage<<"norm(sol_d[0])= "<<norm2(sol_d[0])<<std::endl;
int all_converged = 1;
RealD tmp1,tmp2;
for (k=1;k<=MaxOuterIterations;k++){
a = c /cp;
axpy(p,a,p,r);
// Note to self - direction ps is iterated seperately
// for each shift. Does not appear to have any scope
// for avoiding linear algebra in "single" case.
//
// However SAME r is used. Could load "r" and update
// ALL ps[s]. 2/3 Bandwidth saving
// New Kernel: Load r, vector of coeffs, vector of pointers ps
for(int s=0;s<nshift;s++){
if ( ! converged[s] ) {
if (s==0){
axpy(ps[s],a,ps[s],r);
} else{
RealD as =a *z[s][iz]*bs[s] /(z[s][1-iz]*b);
axpby(ps[s],z[s][iz],as,r,ps[s]);
}
}
}
cp=c;
Linop_f.HermOpAndNorm(p,mmp,d,qq);
axpy(mmp,mass[0],p,mmp);
RealD rn = norm2(p);
d += rn*mass[0];
bp=b;
b=-cp/d;
c=axpy_norm(r,b,mmp,r);
// Toggle the recurrence history
bs[0] = b;
iz = 1-iz;
for(int s=1;s<nshift;s++){
if((!converged[s])){
RealD z0 = z[s][1-iz];
RealD z1 = z[s][iz];
z[s][iz] = z0*z1*bp
/ (b*a*(z1-z0) + z1*bp*(1- (mass[s]-mass[0])*b));
bs[s] = b*z[s][iz]/z0; // NB sign rel to Mike
}
}
axpy(psi,-bs[0],ps[0],psi);
for(int s=0;s<nshift;s++){
int ss = s;
// Scope for optimisation here in case of "single".
// Could load sol_f[0] and pull all ps[s] in.
// if ( single ) ss=primary;
// Bandwith saving in single case is Ls * 3 -> 2+Ls, so ~ 3x saving
// Pipelined CG gain:
//
// New Kernel: Load r, vector of coeffs, vector of pointers ps
// New Kernel: Load sol_f[0], vector of coeffs, vector of pointers ps
// If can predict the coefficient bs then we can fuse these and avoid write reread cyce
// on ps[s].
// Before: 3 x npole + 3 x npole
// After : 2 x npole (ps[s]) => 3x speed up of multishift CG.
if( (!converged[s]) ) {
axpy(sol_f[ss],-bs[s]*alpha[s],ps[s],sol_f[ss]);
}
}
if (k%MaxInnerIterations==0){
// if (c < 1e-4*c_relup){
RealD c_f=c;
precisionChange(tmp_d,psi);
RealD sol_norm =axpy_norm (psi_d,1.,tmp_d,psi_d);
tmp1 = norm2(psi);
zeroit(psi);
tmp2 = norm2(psi);
std::cout<<GridLogMessage<<"k= "<<k<<" norm2(sol)= "<<sol_norm<<" "<<tmp1<<" "<<tmp2<<std::endl;
// precisionChange(sol_d[0],sol_f[0]);
Linop_d.HermOpAndNorm(psi_d,tmp_d,tmp1,tmp2);
axpy(tmp2_d,mass[0],psi_d,tmp_d);
axpy(tmp_d,-1.,tmp2_d,src_d);
precisionChange(r,tmp_d);
c_relup = norm2(r);
std::cout<<GridLogMessage<<"k= "<<k<<" norm2(r)= "<<c<<" "<<c_relup<<" "<<c_f<<std::endl;
if_relup=1;
}
// Convergence checks
all_converged=1;
for(int s=0;s<nshift;s++){
if ( (!converged[s]) ){
RealD css = c * z[s][iz]* z[s][iz];
if(css<rsq[s]){
if ( ! converged[s] )
std::cout<<GridLogMessage<<"ConjugateGradientMultiShift k="<<k<<" Shift "<<s<<" has converged"<<std::endl;
converged[s]=1;
} else {
if (k%MaxInnerIterations==0)
std::cout<<GridLogMessage<<"ConjugateGradientMultiShift k="<<k<<" Shift "<<s<<" has not converged "<<css<<"<"<<rsq[s]<<std::endl;
all_converged=0;
}
}
}
#if 0
if ( all_converged ){
std::cout<<GridLogMessage<< "CGMultiShift: All shifts have converged iteration "<<k<<std::endl;
#else
if ( converged[0] ){
std::cout<<GridLogMessage<< "CGMultiShift: Shift 0 have converged iteration, terminating "<<k<<std::endl;
#endif
#if 1
for(int s=1; s < nshift; s++) {
Linop_f.HermOpAndNorm(sol_f[s],mmp,d,qq);
axpy(tmp,mass[s],sol_f[s],mmp);
axpy(r,-alpha[s],src_f,tmp);
RealD rn = norm2(r);
RealD cn = norm2(src_f);
std::cout<<GridLogMessage<<"CGMultiShift: shift["<<s<<"] true residual "<<std::sqrt(rn/cn)<<std::endl;
}
#endif
iter = k;
break;
}
}
// ugly hack
if ( !all_converged )
std::cout<<GridLogMessage<<"CG multi shift did not converge"<<std::endl;
// assert(0);
}
#endif
InnerCGtimer.Stop();
//Convert sol back to double and add to double prec solution
PrecChangeTimer.Start();
sol_d[0]=psi_d;
for(int i=1;i<nshift;i++)precisionChange(sol_d[i], sol_f[i]);
std::cout<<GridLogMessage<< "CGMultiShift: Checking solutions"<<std::endl;
// Check answers
for(int s=0; s < nshift; s++) {
RealD tmp1,tmp2;
Linop_d.HermOpAndNorm(sol_d[s],tmp_d,tmp1,tmp2);
axpy(tmp2_d,shifts.poles[s],sol_d[s],tmp_d);
axpy(tmp_d,-1.,src_d,tmp2_d);
std::cout<<GridLogMessage<<"CGMultiShift: shift["<<s<<"] true residual "<<std::sqrt(norm2(tmp_d)/norm2(src_d))<<std::endl;
}
PrecChangeTimer.Stop();
}
//Final trial CG
// std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradient: Starting final patch-up double-precision solve"<<std::endl;
TotalTimer.Stop();
std::cout<<GridLogMessage<<"MixedPrecisionConjugateGradient: Total " << TotalTimer.Elapsed() << " Precision change " << PrecChangeTimer.Elapsed() << " Inner CG total " << InnerCGtimer.Elapsed() << std::endl;
}
};
}
#endif

View File

@ -0,0 +1,168 @@
/*************************************************************************************
Grid physics library, www.github.com/paboyle/Grid
Source file: ./lib/algorithms/iterative/ConjugateGradient.h
Copyright (C) 2015
Author: Azusa Yamaguchi <ayamaguc@staffmail.ed.ac.uk>
Author: Peter Boyle <paboyle@ph.ed.ac.uk>
Author: paboyle <paboyle@ph.ed.ac.uk>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#ifndef GRID_CONJUGATE_GRADIENT_SHIFTED_H
#define GRID_CONJUGATE_GRADIENT_SHIFTED_H
namespace Grid {
/////////////////////////////////////////////////////////////
// Base classes for iterative processes based on operators
// single input vec, single output vec.
/////////////////////////////////////////////////////////////
template<class Field>
class ConjugateGradientShifted : public OperatorFunction<Field> {
public:
bool ErrorOnNoConverge; //throw an assert when the CG fails to converge. Defaults true.
RealD Tolerance;
Integer MaxIterations;
ConjugateGradientShifted(RealD tol,Integer maxit, bool err_on_no_conv = true) : Tolerance(tol), MaxIterations(maxit), ErrorOnNoConverge(err_on_no_conv) {
};
void operator() (LinearOperatorBase<Field> &Linop,const Field &src, Field &psi ){
(*this)(Linop,src,psi,NULL);
}
void operator() (LinearOperatorBase<Field> &Linop,const Field &src, Field &psi, RealD *shift){
psi.checkerboard = src.checkerboard;
conformable(psi,src);
RealD cp,c,a,d,b,ssq,qq,b_pred;
Field p(src);
Field mmp(src);
Field r(src);
//Initial residual computation & set up
RealD guess = norm2(psi);
assert(std::isnan(guess)==0);
Linop.HermOpAndNorm(psi,mmp,d,b);
if(shift) axpy(mmp,*shift,psi,mmp);
RealD rn = norm2(psi);
if(shift) d += rn*(*shift);
RealD d2 = real(innerProduct(psi,mmp));
b= norm2(mmp);
RealD src_norm=norm2(src);
r= src-mmp;
p= r;
a =norm2(p);
cp =a;
ssq=norm2(src);
std::cout<<GridLogIterative <<std::setprecision(4)<< "ConjugateGradient: guess "<<guess<<std::endl;
std::cout<<GridLogIterative <<std::setprecision(4)<< "ConjugateGradient: src "<<ssq <<std::endl;
std::cout<<GridLogIterative <<std::setprecision(4)<< "ConjugateGradient: mp "<<d <<std::endl;
std::cout<<GridLogIterative <<std::setprecision(4)<< "ConjugateGradient: mmp "<<b <<std::endl;
std::cout<<GridLogIterative <<std::setprecision(4)<< "ConjugateGradient: cp,r "<<cp <<std::endl;
std::cout<<GridLogIterative <<std::setprecision(4)<< "ConjugateGradient: p "<<a <<std::endl;
RealD rsq = Tolerance* Tolerance*ssq;
//Check if guess is really REALLY good :)
if ( cp <= rsq ) {
return;
}
std::cout<<GridLogIterative << std::setprecision(4)<< "ConjugateGradient: k=0 residual "<<cp<<" target "<<rsq<<std::endl;
GridStopWatch LinalgTimer;
GridStopWatch MatrixTimer;
GridStopWatch SolverTimer;
SolverTimer.Start();
int k;
for (k=1;k<=MaxIterations;k++){
c=cp;
MatrixTimer.Start();
Linop.HermOpAndNorm(p,mmp,d,qq);
MatrixTimer.Stop();
LinalgTimer.Start();
if(shift) axpy(mmp,*shift,p,mmp);
RealD rn = norm2(p);
if(shift) d += rn*(*shift);
RealD d2 = real(innerProduct(p,mmp));
qq = norm2(mmp);
if (k%10==1) std::cout<< std::setprecision(4)<< "d: "<<d<<" d2= "<<d2<<std::endl;
// RealD qqck = norm2(mmp);
// ComplexD dck = innerProduct(p,mmp);
a = c/d;
b_pred = a*(a*qq-d)/c;
cp = axpy_norm(r,-a,mmp,r);
b = cp/c;
if (k%10==1) std::cout<< std::setprecision(4)<<"k= "<<k<<" src: "<<src_norm<<" r= "<<cp<<std::endl;
// Fuse these loops ; should be really easy
psi= a*p+psi;
p = p*b+r;
LinalgTimer.Stop();
std::cout<<GridLogIterative<<"ConjugateGradient: Iteration " <<k<<" residual "<<cp<< " target "<< rsq<<std::endl;
// Stopping condition
if ( cp <= rsq ) {
SolverTimer.Stop();
Linop.HermOpAndNorm(psi,mmp,d,qq);
if(shift) mmp = mmp + (*shift) * psi;
p=mmp-src;
RealD mmpnorm = sqrt(norm2(mmp));
RealD psinorm = sqrt(norm2(psi));
RealD srcnorm = sqrt(norm2(src));
RealD resnorm = sqrt(norm2(p));
RealD true_residual = resnorm/srcnorm;
std::cout<<GridLogMessage<<"ConjugateGradient: Converged on iteration " <<k
<<" computed residual "<<sqrt(cp/ssq)
<<" true residual " <<true_residual
<<" target "<<Tolerance<<std::endl;
std::cout<<GridLogMessage<<"Time elapsed: Total "<< SolverTimer.Elapsed() << " Matrix "<<MatrixTimer.Elapsed() << " Linalg "<<LinalgTimer.Elapsed();
std::cout<<std::endl;
if(ErrorOnNoConverge)
assert(true_residual/Tolerance < 1000.0);
return;
}
}
std::cout<<GridLogMessage<<"ConjugateGradient did NOT converge"<<std::endl;
// assert(0);
}
};
}
#endif

View File

@ -31,11 +31,16 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
#include <string.h> //memset
#ifdef USE_LAPACK
#ifdef USE_MKL
#include<mkl_lapack.h>
#else
void LAPACK_dstegr(char *jobz, char *range, int *n, double *d, double *e,
double *vl, double *vu, int *il, int *iu, double *abstol,
int *m, double *w, double *z, int *ldz, int *isuppz,
double *work, int *lwork, int *iwork, int *liwork,
int *info);
//#include <lapacke/lapacke.h>
#endif
#endif
#include "DenseMatrix.h"
#include "EigenSort.h"
@ -59,15 +64,16 @@ public:
int Nstop; // Number of evecs checked for convergence
int Nk; // Number of converged sought
int Np; // Np -- Number of spare vecs in krylov space
int Np; // Np -- Number of spare vecs in kryloc space
int Nm; // Nm -- total number of vectors
RealD OrthoTime;
RealD eresid;
SortEigen<Field> _sort;
// GridCartesian &_fgrid;
LinearOperatorBase<Field> &_Linop;
OperatorFunction<Field> &_poly;
@ -124,23 +130,23 @@ public:
GridBase *grid = evec[0]._grid;
Field w(grid);
std::cout << "RitzMatrix "<<std::endl;
std::cout<<GridLogMessage << "RitzMatrix "<<std::endl;
for(int i=0;i<k;i++){
_poly(_Linop,evec[i],w);
std::cout << "["<<i<<"] ";
std::cout<<GridLogMessage << "["<<i<<"] ";
for(int j=0;j<k;j++){
ComplexD in = innerProduct(evec[j],w);
if ( fabs((double)i-j)>1 ) {
if (abs(in) >1.0e-9 ) {
std::cout<<"oops"<<std::endl;
std::cout<<GridLogMessage<<"oops"<<std::endl;
abort();
} else
std::cout << " 0 ";
std::cout<<GridLogMessage << " 0 ";
} else {
std::cout << " "<<in<<" ";
std::cout<<GridLogMessage << " "<<in<<" ";
}
}
std::cout << std::endl;
std::cout<<GridLogMessage << std::endl;
}
}
@ -174,10 +180,10 @@ public:
RealD beta = normalise(w); // 6. βk+1 := ∥wk∥2. If βk+1 = 0 then Stop
// 7. vk+1 := wk/βk+1
// std::cout << "alpha = " << zalph << " beta "<<beta<<std::endl;
std::cout<<GridLogMessage << "alpha = " << zalph << " beta "<<beta<<std::endl;
const RealD tiny = 1.0e-20;
if ( beta < tiny ) {
std::cout << " beta is tiny "<<beta<<std::endl;
std::cout<<GridLogMessage << " beta is tiny "<<beta<<std::endl;
}
lmd[k] = alph;
lme[k] = beta;
@ -253,6 +259,7 @@ public:
}
#ifdef USE_LAPACK
#define LAPACK_INT long long
void diagonalize_lapack(DenseVector<RealD>& lmd,
DenseVector<RealD>& lme,
int N1,
@ -262,7 +269,7 @@ public:
const int size = Nm;
// tevals.resize(size);
// tevecs.resize(size);
int NN = N1;
LAPACK_INT NN = N1;
double evals_tmp[NN];
double evec_tmp[NN][NN];
memset(evec_tmp[0],0,sizeof(double)*NN*NN);
@ -276,19 +283,19 @@ public:
if (i==j) evals_tmp[i] = lmd[i];
if (j==(i-1)) EE[j] = lme[j];
}
int evals_found;
int lwork = ( (18*NN) > (1+4*NN+NN*NN)? (18*NN):(1+4*NN+NN*NN)) ;
int liwork = 3+NN*10 ;
int iwork[liwork];
LAPACK_INT evals_found;
LAPACK_INT lwork = ( (18*NN) > (1+4*NN+NN*NN)? (18*NN):(1+4*NN+NN*NN)) ;
LAPACK_INT liwork = 3+NN*10 ;
LAPACK_INT iwork[liwork];
double work[lwork];
int isuppz[2*NN];
LAPACK_INT isuppz[2*NN];
char jobz = 'V'; // calculate evals & evecs
char range = 'I'; // calculate all evals
// char range = 'A'; // calculate all evals
char uplo = 'U'; // refer to upper half of original matrix
char compz = 'I'; // Compute eigenvectors of tridiagonal matrix
int ifail[NN];
int info;
long long info;
// int total = QMP_get_number_of_nodes();
// int node = QMP_get_node_number();
// GridBase *grid = evec[0]._grid;
@ -296,14 +303,18 @@ public:
int node = grid->_processor;
int interval = (NN/total)+1;
double vl = 0.0, vu = 0.0;
int il = interval*node+1 , iu = interval*(node+1);
LAPACK_INT il = interval*node+1 , iu = interval*(node+1);
if (iu > NN) iu=NN;
double tol = 0.0;
if (1) {
memset(evals_tmp,0,sizeof(double)*NN);
if ( il <= NN){
printf("total=%d node=%d il=%d iu=%d\n",total,node,il,iu);
#ifdef USE_MKL
dstegr(&jobz, &range, &NN,
#else
LAPACK_dstegr(&jobz, &range, &NN,
#endif
(double*)DD, (double*)EE,
&vl, &vu, &il, &iu, // these four are ignored if second parameteris 'A'
&tol, // tolerance
@ -335,6 +346,7 @@ public:
lmd [NN-1-i]=evals_tmp[i];
}
}
#undef LAPACK_INT
#endif
@ -365,12 +377,14 @@ public:
// diagonalize_lapack(lmd2,lme2,Nm2,Nm,Qt,grid);
#endif
int Niter = 100*N1;
int Niter = 10000*N1;
int kmin = 1;
int kmax = N2;
// (this should be more sophisticated)
for(int iter=0; iter<Niter; ++iter){
for(int iter=0; ; ++iter){
if ( (iter+1)%(100*N1)==0)
std::cout<<GridLogMessage << "[QL method] Not converged - iteration "<<iter+1<<"\n";
// determination of 2x2 leading submatrix
RealD dsub = lmd[kmax-1]-lmd[kmax-2];
@ -399,11 +413,11 @@ public:
_sort.push(lmd3,N2);
_sort.push(lmd2,N2);
for(int k=0; k<N2; ++k){
if (fabs(lmd2[k] - lmd3[k]) >SMALL) std::cout <<"lmd(qr) lmd(lapack) "<< k << ": " << lmd2[k] <<" "<< lmd3[k] <<std::endl;
// if (fabs(lme2[k] - lme[k]) >SMALL) std::cout <<"lme(qr)-lme(lapack) "<< k << ": " << lme2[k] - lme[k] <<std::endl;
if (fabs(lmd2[k] - lmd3[k]) >SMALL) std::cout<<GridLogMessage <<"lmd(qr) lmd(lapack) "<< k << ": " << lmd2[k] <<" "<< lmd3[k] <<std::endl;
// if (fabs(lme2[k] - lme[k]) >SMALL) std::cout<<GridLogMessage <<"lme(qr)-lme(lapack) "<< k << ": " << lme2[k] - lme[k] <<std::endl;
}
for(int k=0; k<N1*N1; ++k){
// if (fabs(Qt2[k] - Qt[k]) >SMALL) std::cout <<"Qt(qr)-Qt(lapack) "<< k << ": " << Qt2[k] - Qt[k] <<std::endl;
// if (fabs(Qt2[k] - Qt[k]) >SMALL) std::cout<<GridLogMessage <<"Qt(qr)-Qt(lapack) "<< k << ": " << Qt2[k] - Qt[k] <<std::endl;
}
}
#endif
@ -418,7 +432,7 @@ public:
}
}
}
std::cout << "[QL method] Error - Too many iteration: "<<Niter<<"\n";
std::cout<<GridLogMessage << "[QL method] Error - Too many iteration: "<<Niter<<"\n";
abort();
}
@ -435,6 +449,7 @@ public:
DenseVector<Field>& evec,
int k)
{
double t0=-usecond()/1e6;
typedef typename Field::scalar_type MyComplex;
MyComplex ip;
@ -453,6 +468,8 @@ public:
w = w - ip * evec[j];
}
normalise(w);
t0+=usecond()/1e6;
OrthoTime +=t0;
}
void setUnit_Qt(int Nm, DenseVector<RealD> &Qt) {
@ -486,10 +503,10 @@ until convergence
GridBase *grid = evec[0]._grid;
assert(grid == src._grid);
std::cout << " -- Nk = " << Nk << " Np = "<< Np << std::endl;
std::cout << " -- Nm = " << Nm << std::endl;
std::cout << " -- size of eval = " << eval.size() << std::endl;
std::cout << " -- size of evec = " << evec.size() << std::endl;
std::cout<<GridLogMessage << " -- Nk = " << Nk << " Np = "<< Np << std::endl;
std::cout<<GridLogMessage << " -- Nm = " << Nm << std::endl;
std::cout<<GridLogMessage << " -- size of eval = " << eval.size() << std::endl;
std::cout<<GridLogMessage << " -- size of evec = " << evec.size() << std::endl;
assert(Nm == evec.size() && Nm == eval.size());
@ -500,6 +517,7 @@ until convergence
DenseVector<int> Iconv(Nm);
DenseVector<Field> B(Nm,grid); // waste of space replicating
// DenseVector<Field> Btemp(Nm,grid); // waste of space replicating
Field f(grid);
Field v(grid);
@ -515,35 +533,48 @@ until convergence
// (uniform vector) Why not src??
// evec[0] = 1.0;
evec[0] = src;
std:: cout <<"norm2(src)= " << norm2(src)<<std::endl;
std:: cout<<GridLogMessage <<"norm2(src)= " << norm2(src)<<std::endl;
// << src._grid << std::endl;
normalise(evec[0]);
std:: cout <<"norm2(evec[0])= " << norm2(evec[0]) <<std::endl;
std:: cout<<GridLogMessage <<"norm2(evec[0])= " << norm2(evec[0]) <<std::endl;
// << evec[0]._grid << std::endl;
// Initial Nk steps
OrthoTime=0.;
double t0=usecond()/1e6;
for(int k=0; k<Nk; ++k) step(eval,lme,evec,f,Nm,k);
// std:: cout <<"norm2(evec[1])= " << norm2(evec[1]) << std::endl;
// std:: cout <<"norm2(evec[2])= " << norm2(evec[2]) << std::endl;
double t1=usecond()/1e6;
std::cout<<GridLogMessage <<"IRL::Initial steps: "<<t1-t0<< "seconds"<<std::endl; t0=t1;
std::cout<<GridLogMessage <<"IRL::Initial steps:OrthoTime "<<OrthoTime<< "seconds"<<std::endl;
// std:: cout<<GridLogMessage <<"norm2(evec[1])= " << norm2(evec[1]) << std::endl;
// std:: cout<<GridLogMessage <<"norm2(evec[2])= " << norm2(evec[2]) << std::endl;
RitzMatrix(evec,Nk);
t1=usecond()/1e6;
std::cout<<GridLogMessage <<"IRL::RitzMatrix: "<<t1-t0<< "seconds"<<std::endl; t0=t1;
for(int k=0; k<Nk; ++k){
// std:: cout <<"eval " << k << " " <<eval[k] << std::endl;
// std:: cout <<"lme " << k << " " << lme[k] << std::endl;
// std:: cout<<GridLogMessage <<"eval " << k << " " <<eval[k] << std::endl;
// std:: cout<<GridLogMessage <<"lme " << k << " " << lme[k] << std::endl;
}
// Restarting loop begins
for(int iter = 0; iter<Niter; ++iter){
std::cout<<"\n Restart iteration = "<< iter << std::endl;
std::cout<<GridLogMessage<<"\n Restart iteration = "<< iter << std::endl;
//
// Rudy does a sort first which looks very different. Getting fed up with sorting out the algo defs.
// We loop over
//
OrthoTime=0.;
for(int k=Nk; k<Nm; ++k) step(eval,lme,evec,f,Nm,k);
t1=usecond()/1e6;
std::cout<<GridLogMessage <<"IRL:: "<<Np <<" steps: "<<t1-t0<< "seconds"<<std::endl; t0=t1;
std::cout<<GridLogMessage <<"IRL::Initial steps:OrthoTime "<<OrthoTime<< "seconds"<<std::endl;
f *= lme[Nm-1];
RitzMatrix(evec,k2);
t1=usecond()/1e6;
std::cout<<GridLogMessage <<"IRL:: RitzMatrix: "<<t1-t0<< "seconds"<<std::endl; t0=t1;
// getting eigenvalues
for(int k=0; k<Nm; ++k){
@ -552,18 +583,27 @@ until convergence
}
setUnit_Qt(Nm,Qt);
diagonalize(eval2,lme2,Nm,Nm,Qt,grid);
t1=usecond()/1e6;
std::cout<<GridLogMessage <<"IRL:: diagonalize: "<<t1-t0<< "seconds"<<std::endl; t0=t1;
// sorting
_sort.push(eval2,Nm);
t1=usecond()/1e6;
std::cout<<GridLogMessage <<"IRL:: eval sorting: "<<t1-t0<< "seconds"<<std::endl; t0=t1;
// Implicitly shifted QR transformations
setUnit_Qt(Nm,Qt);
for(int ip=0; ip<k2; ++ip){
std::cout<<GridLogMessage << "eval "<< ip << " "<< eval2[ip] << std::endl;
}
for(int ip=k2; ip<Nm; ++ip){
std::cout << "qr_decomp "<< ip << " "<< eval2[ip] << std::endl;
std::cout<<GridLogMessage << "qr_decomp "<< ip << " "<< eval2[ip] << std::endl;
qr_decomp(eval,lme,Nm,Nm,Qt,eval2[ip],k1,Nm);
}
t1=usecond()/1e6;
std::cout<<GridLogMessage <<"IRL::qr_decomp: "<<t1-t0<< "seconds"<<std::endl; t0=t1;
if (0) {
for(int i=0; i<(Nk+1); ++i) B[i] = 0.0;
for(int j=k1-1; j<k2+1; ++j){
@ -572,14 +612,38 @@ until convergence
B[j] += Qt[k+Nm*j] * evec[k];
}
}
for(int j=k1-1; j<k2+1; ++j) evec[j] = B[j];
t1=usecond()/1e6;
std::cout<<GridLogMessage <<"IRL::QR Rotate: "<<t1-t0<< "seconds"<<std::endl; t0=t1;
}
if (1) {
for(int i=0; i<(Nk+1); ++i) {
B[i] = 0.0;
B[i].checkerboard = evec[0].checkerboard;
}
int j_block = 24; int k_block=24;
PARALLEL_FOR_LOOP
for(int ss=0;ss < grid->oSites();ss++){
for(int jj=k1-1; jj<k2+1; jj += j_block)
for(int kk=0; kk<Nm; kk += k_block)
for(int j=jj; (j<(k2+1)) && j<(jj+j_block); ++j){
for(int k=kk; (k<Nm) && k<(kk+k_block) ; ++k){
B[j]._odata[ss] +=Qt[k+Nm*j] * evec[k]._odata[ss];
}
}
}
t1=usecond()/1e6;
std::cout<<GridLogMessage <<"IRL::QR rotation: "<<t1-t0<< "seconds"<<std::endl; t0=t1;
}
for(int j=k1-1; j<k2+1; ++j) evec[j] = B[j];
// Compressed vector f and beta(k2)
f *= Qt[Nm-1+Nm*(k2-1)];
f += lme[k2-1] * evec[k2];
beta_k = norm2(f);
beta_k = sqrt(beta_k);
std::cout<<" beta(k) = "<<beta_k<<std::endl;
std::cout<<GridLogMessage<<" beta(k) = "<<beta_k<<std::endl;
RealD betar = 1.0/beta_k;
evec[k2] = betar * f;
@ -592,7 +656,10 @@ until convergence
}
setUnit_Qt(Nm,Qt);
diagonalize(eval2,lme2,Nk,Nm,Qt,grid);
t1=usecond()/1e6;
std::cout<<GridLogMessage <<"IRL::diagonalize: "<<t1-t0<< "seconds"<<std::endl; t0=t1;
if (0) {
for(int k = 0; k<Nk; ++k) B[k]=0.0;
for(int j = 0; j<Nk; ++j){
@ -600,12 +667,34 @@ until convergence
B[j].checkerboard = evec[k].checkerboard;
B[j] += Qt[k+j*Nm] * evec[k];
}
// std::cout << "norm(B["<<j<<"])="<<norm2(B[j])<<std::endl;
std::cout<<GridLogMessage << "norm(B["<<j<<"])="<<norm2(B[j])<<std::endl;
}
// _sort.push(eval2,B,Nk);
t1=usecond()/1e6;
std::cout<<GridLogMessage <<"IRL::Convergence rotation: "<<t1-t0<< "seconds"<<std::endl; t0=t1;
}
if (1) {
for(int i=0; i<(Nk+1); ++i) {
B[i] = 0.0;
B[i].checkerboard = evec[0].checkerboard;
}
int j_block = 24; int k_block=24;
PARALLEL_FOR_LOOP
for(int ss=0;ss < grid->oSites();ss++){
for(int jj=0; jj<Nk; jj += j_block)
for(int kk=0; kk<Nk; kk += k_block)
for(int j=jj; (j<Nk) && j<(jj+j_block); ++j){
for(int k=kk; (k<Nk) && k<(kk+k_block) ; ++k){
B[j]._odata[ss] +=Qt[k+Nm*j] * evec[k]._odata[ss];
}
}
}
t1=usecond()/1e6;
std::cout<<GridLogMessage <<"IRL::convergence rotation : "<<t1-t0<< "seconds"<<std::endl; t0=t1;
}
Nconv = 0;
// std::cout << std::setiosflags(std::ios_base::scientific);
// std::cout<<GridLogMessage << std::setiosflags(std::ios_base::scientific);
for(int i=0; i<Nk; ++i){
// _poly(_Linop,B[i],v);
@ -613,14 +702,16 @@ until convergence
RealD vnum = real(innerProduct(B[i],v)); // HermOp.
RealD vden = norm2(B[i]);
RealD vv0 = norm2(v);
eval2[i] = vnum/vden;
v -= eval2[i]*B[i];
RealD vv = norm2(v);
std::cout.precision(13);
std::cout << "[" << std::setw(3)<< std::setiosflags(std::ios_base::right) <<i<<"] ";
std::cout << "eval = "<<std::setw(25)<< std::setiosflags(std::ios_base::left)<< eval2[i];
std::cout <<" |H B[i] - eval[i]B[i]|^2 "<< std::setw(25)<< std::setiosflags(std::ios_base::right)<< vv<< std::endl;
std::cout<<GridLogMessage << "[" << std::setw(3)<< std::setiosflags(std::ios_base::right) <<i<<"] ";
std::cout<<"eval = "<<std::setw(25)<< std::setiosflags(std::ios_base::left)<< eval2[i];
std::cout<<"|H B[i] - eval[i]B[i]|^2 "<< std::setw(25)<< std::setiosflags(std::ios_base::right)<< vv;
std::cout<<" "<< vnum/(sqrt(vden)*sqrt(vv0)) << std::endl;
// change the criteria as evals are supposed to be sorted, all evals smaller(larger) than Nstop should have converged
if((vv<eresid*eresid) && (i == Nconv) ){
@ -629,17 +720,19 @@ until convergence
}
} // i-loop end
// std::cout << std::resetiosflags(std::ios_base::scientific);
// std::cout<<GridLogMessage << std::resetiosflags(std::ios_base::scientific);
t1=usecond()/1e6;
std::cout<<GridLogMessage <<"IRL::convergence testing: "<<t1-t0<< "seconds"<<std::endl; t0=t1;
std::cout<<" #modes converged: "<<Nconv<<std::endl;
std::cout<<GridLogMessage<<" #modes converged: "<<Nconv<<std::endl;
if( Nconv>=Nstop ){
goto converged;
}
} // end of iter loop
std::cout<<"\n NOT converged.\n";
std::cout<<GridLogMessage<<"\n NOT converged.\n";
abort();
converged:
@ -652,10 +745,10 @@ until convergence
}
_sort.push(eval,evec,Nconv);
std::cout << "\n Converged\n Summary :\n";
std::cout << " -- Iterations = "<< Nconv << "\n";
std::cout << " -- beta(k) = "<< beta_k << "\n";
std::cout << " -- Nconv = "<< Nconv << "\n";
std::cout<<GridLogMessage << "\n Converged\n Summary :\n";
std::cout<<GridLogMessage << " -- Iterations = "<< Nconv << "\n";
std::cout<<GridLogMessage << " -- beta(k) = "<< beta_k << "\n";
std::cout<<GridLogMessage << " -- Nconv = "<< Nconv << "\n";
}
/////////////////////////////////////////////////
@ -678,25 +771,25 @@ until convergence
}
}
std::cout<<"Lanczos_Factor start/end " <<start <<"/"<<end<<std::endl;
std::cout<<GridLogMessage<<"Lanczos_Factor start/end " <<start <<"/"<<end<<std::endl;
// Starting from scratch, bq[0] contains a random vector and |bq[0]| = 1
int first;
if(start == 0){
std::cout << "start == 0\n"; //TESTING
std::cout<<GridLogMessage << "start == 0\n"; //TESTING
_poly(_Linop,bq[0],bf);
alpha = real(innerProduct(bq[0],bf));//alpha = bq[0]^dag A bq[0]
std::cout << "alpha = " << alpha << std::endl;
std::cout<<GridLogMessage << "alpha = " << alpha << std::endl;
bf = bf - alpha * bq[0]; //bf = A bq[0] - alpha bq[0]
H[0][0]=alpha;
std::cout << "Set H(0,0) to " << H[0][0] << std::endl;
std::cout<<GridLogMessage << "Set H(0,0) to " << H[0][0] << std::endl;
first = 1;
@ -716,19 +809,19 @@ until convergence
beta = 0;sqbt = 0;
std::cout << "cont is true so setting beta to zero\n";
std::cout<<GridLogMessage << "cont is true so setting beta to zero\n";
} else {
beta = norm2(bf);
sqbt = sqrt(beta);
std::cout << "beta = " << beta << std::endl;
std::cout<<GridLogMessage << "beta = " << beta << std::endl;
}
for(int j=first;j<end;j++){
std::cout << "Factor j " << j <<std::endl;
std::cout<<GridLogMessage << "Factor j " << j <<std::endl;
if(cont){ // switches to factoring; understand start!=0 and initial bf value is right.
bq[j] = bf; cont = false;
@ -751,7 +844,7 @@ until convergence
beta = fnorm;
sqbt = sqrt(beta);
std::cout << "alpha = " << alpha << " fnorm = " << fnorm << '\n';
std::cout<<GridLogMessage << "alpha = " << alpha << " fnorm = " << fnorm << '\n';
///Iterative refinement of orthogonality V = [ bq[0] bq[1] ... bq[M] ]
int re = 0;
@ -786,8 +879,8 @@ until convergence
bck = sqrt( nmbex );
re++;
}
std::cout << "Iteratively refined orthogonality, changes alpha\n";
if(re > 1) std::cout << "orthagonality refined " << re << " times" <<std::endl;
std::cout<<GridLogMessage << "Iteratively refined orthogonality, changes alpha\n";
if(re > 1) std::cout<<GridLogMessage << "orthagonality refined " << re << " times" <<std::endl;
H[j][j]=alpha;
}
@ -802,11 +895,13 @@ until convergence
void ImplicitRestart(int TM, DenseVector<RealD> &evals, DenseVector<DenseVector<RealD> > &evecs, DenseVector<Field> &bq, Field &bf, int cont)
{
std::cout << "ImplicitRestart begin. Eigensort starting\n";
std::cout<<GridLogMessage << "ImplicitRestart begin. Eigensort starting\n";
DenseMatrix<RealD> H; Resize(H,Nm,Nm);
#ifndef USE_LAPACK
EigenSort(evals, evecs);
#endif
///Assign shifts
int K=Nk;
@ -829,15 +924,15 @@ until convergence
/// Shifted H defines a new K step Arnoldi factorization
RealD beta = H[ff][ff-1];
RealD sig = Q[TM - 1][ff - 1];
std::cout << "beta = " << beta << " sig = " << real(sig) <<std::endl;
std::cout<<GridLogMessage << "beta = " << beta << " sig = " << real(sig) <<std::endl;
std::cout << "TM = " << TM << " ";
std::cout << norm2(bq[0]) << " -- before" <<std::endl;
std::cout<<GridLogMessage << "TM = " << TM << " ";
std::cout<<GridLogMessage << norm2(bq[0]) << " -- before" <<std::endl;
/// q -> q Q
times_real(bq, Q, TM);
std::cout << norm2(bq[0]) << " -- after " << ff <<std::endl;
std::cout<<GridLogMessage << norm2(bq[0]) << " -- after " << ff <<std::endl;
bf = beta* bq[ff] + sig* bf;
/// Do the rest of the factorization
@ -861,7 +956,7 @@ until convergence
int ff = Lanczos_Factor(0, M, cont, bq,bf,H); // 0--M to begin with
if(ff < M) {
std::cout << "Krylov: aborting ff "<<ff <<" "<<M<<std::endl;
std::cout<<GridLogMessage << "Krylov: aborting ff "<<ff <<" "<<M<<std::endl;
abort(); // Why would this happen?
}
@ -870,7 +965,7 @@ until convergence
for(int it = 0; it < Niter && (converged < Nk); ++it) {
std::cout << "Krylov: Iteration --> " << it << std::endl;
std::cout<<GridLogMessage << "Krylov: Iteration --> " << it << std::endl;
int lock_num = lock ? converged : 0;
DenseVector<RealD> tevals(M - lock_num );
DenseMatrix<RealD> tevecs; Resize(tevecs,M - lock_num,M - lock_num);
@ -886,7 +981,7 @@ until convergence
Wilkinson<RealD>(H, evals, evecs, small);
// Check();
std::cout << "Done "<<std::endl;
std::cout<<GridLogMessage << "Done "<<std::endl;
}
@ -951,7 +1046,7 @@ until convergence
DenseVector<RealD> &tevals, DenseVector<DenseVector<RealD> > &tevecs,
int lock, int converged)
{
std::cout << "Converged " << converged << " so far." << std::endl;
std::cout<<GridLogMessage << "Converged " << converged << " so far." << std::endl;
int lock_num = lock ? converged : 0;
int M = Nm;
@ -966,7 +1061,9 @@ until convergence
RealD small=1.0e-16;
Wilkinson<RealD>(AH, tevals, tevecs, small);
#ifndef USE_LAPACK
EigenSort(tevals, tevecs);
#endif
RealD resid_nrm= norm2(bf);
@ -977,7 +1074,7 @@ until convergence
RealD diff = 0;
diff = abs( tevecs[i][Nm - 1 - lock_num] ) * resid_nrm;
std::cout << "residual estimate " << SS-1-i << " " << diff << " of (" << tevals[i] << ")" << std::endl;
std::cout<<GridLogMessage << "residual estimate " << SS-1-i << " " << diff << " of (" << tevals[i] << ")" << std::endl;
if(diff < converged) {
@ -993,13 +1090,13 @@ until convergence
lock_num++;
}
converged++;
std::cout << " converged on eval " << converged << " of " << Nk << std::endl;
std::cout<<GridLogMessage << " converged on eval " << converged << " of " << Nk << std::endl;
} else {
break;
}
}
#endif
std::cout << "Got " << converged << " so far " <<std::endl;
std::cout<<GridLogMessage << "Got " << converged << " so far " <<std::endl;
}
///Check
@ -1008,7 +1105,9 @@ until convergence
DenseVector<RealD> goodval(this->get);
#ifndef USE_LAPACK
EigenSort(evals,evecs);
#endif
int NM = Nm;
@ -1080,10 +1179,10 @@ say con = 2
**/
template<class T>
static void Lock(DenseMatrix<T> &H, // Hess mtx
DenseMatrix<T> &Q, // Lock Transform
T val, // value to be locked
int con, // number already locked
static void Lock(DenseMatrix<T> &H, ///Hess mtx
DenseMatrix<T> &Q, ///Lock Transform
T val, ///value to be locked
int con, ///number already locked
RealD small,
int dfg,
bool herm)

View File

@ -77,7 +77,7 @@ public:
// GridCartesian / GridRedBlackCartesian
////////////////////////////////////////////////////////////////
virtual int CheckerBoarded(int dim)=0;
virtual int CheckerBoard(std::vector<int> &site)=0;
virtual int CheckerBoard(const std::vector<int> &site)=0;
virtual int CheckerBoardDestination(int source_cb,int shift,int dim)=0;
virtual int CheckerBoardShift(int source_cb,int dim,int shift,int osite)=0;
virtual int CheckerBoardShiftForCB(int source_cb,int dim,int shift,int cb)=0;

View File

@ -49,7 +49,7 @@ public:
virtual int CheckerBoarded(int dim){
return 0;
}
virtual int CheckerBoard(std::vector<int> &site){
virtual int CheckerBoard(const std::vector<int> &site){
return 0;
}
virtual int CheckerBoardDestination(int cb,int shift,int dim){

View File

@ -49,7 +49,7 @@ public:
if( dim==_checker_dim) return 1;
else return 0;
}
virtual int CheckerBoard(std::vector<int> &site){
virtual int CheckerBoard(const std::vector<int> &site){
int linear=0;
assert(site.size()==_ndimension);
for(int d=0;d<_ndimension;d++){

View File

@ -25,7 +25,7 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include "Grid.h"
#include <Grid/Grid.h>
namespace Grid {
///////////////////////////////////////////////////////////////
@ -65,7 +65,6 @@ const std::vector<int> & CartesianCommunicator::ThisProcessorCoor(void) { return
const std::vector<int> & CartesianCommunicator::ProcessorGrid(void) { return _processors; };
int CartesianCommunicator::ProcessorCount(void) { return _Nprocessors; };
////////////////////////////////////////////////////////////////////////////////
// very VERY rarely (Log, serial RNG) we need world without a grid
////////////////////////////////////////////////////////////////////////////////
@ -90,11 +89,11 @@ void CartesianCommunicator::GlobalSumVector(ComplexD *c,int N)
#if !defined( GRID_COMMS_MPI3) && !defined (GRID_COMMS_MPI3L)
void CartesianCommunicator::StencilSendToRecvFromBegin(std::vector<CommsRequest_t> &list,
void *xmit,
int xmit_to_rank,
void *recv,
int recv_from_rank,
int bytes)
void *xmit,
int xmit_to_rank,
void *recv,
int recv_from_rank,
int bytes)
{
SendToRecvFromBegin(list,xmit,xmit_to_rank,recv,recv_from_rank,bytes);
}

View File

@ -68,8 +68,6 @@ class CartesianCommunicator {
static MPI_Comm communicator_world;
MPI_Comm communicator;
typedef MPI_Request CommsRequest_t;
static char name[MPI_MAX_PROCESSOR_NAME]; // processing node physical name
static int length;
#else
typedef int CommsRequest_t;
#endif
@ -151,7 +149,6 @@ class CartesianCommunicator {
const std::vector<int> & ProcessorGrid(void) ;
int ProcessorCount(void) ;
void PrintRankInfo(void) ;
////////////////////////////////////////////////////////////////////////////////
// very VERY rarely (Log, serial RNG) we need world without a grid
////////////////////////////////////////////////////////////////////////////////

View File

@ -25,7 +25,7 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include "Grid.h"
#include <Grid/Grid.h>
#include <mpi.h>
namespace Grid {
@ -35,8 +35,6 @@ namespace Grid {
// Info that is setup once and indept of cartesian layout
///////////////////////////////////////////////////////////////////////////////////////////////////
MPI_Comm CartesianCommunicator::communicator_world;
char CartesianCommunicator::name[MPI_MAX_PROCESSOR_NAME]; // processing node physical name
int CartesianCommunicator::length;
// Should error check all MPI calls.
void CartesianCommunicator::Init(int *argc, char ***argv) {
@ -46,8 +44,6 @@ void CartesianCommunicator::Init(int *argc, char ***argv) {
MPI_Init(argc,argv);
}
MPI_Comm_dup (MPI_COMM_WORLD,&communicator_world);
MPI_Get_processor_name(name, &length);
ShmInitGeneric();
}
@ -210,10 +206,5 @@ void CartesianCommunicator::BroadcastWorld(int root,void* data, int bytes)
assert(ierr==0);
}
void CartesianCommunicator::PrintRankInfo(){
std::cout << "Grid: Rank "<< _processor << " - Physical node name: " << name << std::endl;
}
}// end of namespace

View File

@ -25,7 +25,7 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include "Grid.h"
#include <Grid/Grid.h>
#include <mpi.h>
namespace Grid {
@ -576,10 +576,5 @@ void CartesianCommunicator::BroadcastWorld(int root,void* data, int bytes)
assert(ierr==0);
}
void CartesianCommunicator::PrintRankInfo(){
std::cout << "Grid: Rank "<< _processor << " - Physical node name: " << name << std::endl;
}
}

View File

@ -869,9 +869,6 @@ void *CartesianCommunicator::ShmBufferTranslate(int rank,void * local_p) {
return NULL;
}
void CartesianCommunicator::PrintRankInfo(){
std::cout << "Grid: Rank "<< _processor << " - Physical node name: " << name << std::endl;
}
};

View File

@ -25,7 +25,7 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include "Grid.h"
#include <Grid/Grid.h>
namespace Grid {
///////////////////////////////////////////////////////////////////////////////////////////////////
@ -37,11 +37,6 @@ void CartesianCommunicator::Init(int *argc, char *** arv)
ShmInitGeneric();
}
void CartesianCommunicator::PrintRankInfo(){
std::cout << GridLogMessage << "No Rank Info available" << std::endl;
}
CartesianCommunicator::CartesianCommunicator(const std::vector<int> &processors)
{
_processors = processors;
@ -65,10 +60,10 @@ void CartesianCommunicator::GlobalSum(uint64_t &){}
void CartesianCommunicator::GlobalSumVector(double *,int N){}
void CartesianCommunicator::SendRecvPacket(void *xmit,
void *recv,
int xmit_to_rank,
int recv_from_rank,
int bytes)
void *recv,
int xmit_to_rank,
int recv_from_rank,
int bytes)
{
assert(0);
}
@ -76,19 +71,19 @@ void CartesianCommunicator::SendRecvPacket(void *xmit,
// Basic Halo comms primitive -- should never call in single node
void CartesianCommunicator::SendToRecvFrom(void *xmit,
int dest,
void *recv,
int from,
int bytes)
int dest,
void *recv,
int from,
int bytes)
{
assert(0);
}
void CartesianCommunicator::SendToRecvFromBegin(std::vector<CommsRequest_t> &list,
void *xmit,
int dest,
void *recv,
int from,
int bytes)
void *xmit,
int dest,
void *recv,
int from,
int bytes)
{
assert(0);
}

View File

@ -25,7 +25,7 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include "Grid.h"
#include <Grid/Grid.h>
#include <mpp/shmem.h>
namespace Grid {
@ -333,9 +333,5 @@ void CartesianCommunicator::BroadcastWorld(int root,void* data, int bytes)
}
}
void CartesianCommunicator::PrintRankInfo(){
std::cout << GridLogMessage << "SHMEM: Rank Info not implemented yet" << std::endl;
}
}

View File

@ -86,7 +86,7 @@ PARALLEL_FOR_LOOP
// Poke a scalar object into the SIMD array
//////////////////////////////////////////////////////
template<class vobj,class sobj>
void pokeSite(const sobj &s,Lattice<vobj> &l,std::vector<int> &site){
void pokeSite(const sobj &s,Lattice<vobj> &l,const std::vector<int> &site){
GridBase *grid=l._grid;
@ -120,7 +120,7 @@ PARALLEL_FOR_LOOP
// Peek a scalar object from the SIMD array
//////////////////////////////////////////////////////////
template<class vobj,class sobj>
void peekSite(sobj &s,const Lattice<vobj> &l,std::vector<int> &site){
void peekSite(sobj &s,const Lattice<vobj> &l,const std::vector<int> &site){
GridBase *grid=l._grid;

View File

@ -31,87 +31,6 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
#define GRID_LATTICE_REDUCTION_H
namespace Grid {
template <class T>
class ReproducibilityState {
public:
typedef typename T::vector_type vector_type;
typedef std::vector<vector_type, alignedAllocator<vector_type> > sum_type;
unsigned int n_call;
bool do_check;
bool enable_reprocheck;
bool success;
unsigned int interval;
std::vector<sum_type> th_states;
void reset_counter() { n_call = 0; }
void reset() {
th_states.clear();
do_check = false;
enable_reprocheck = false;
success = true;
n_call = 0;
};
ReproducibilityState():interval(1) {
reset();
}
void check(GridBase* grid, sum_type &sumarray){
/////////////////////// Reproducibility section, not threaded on purpouse
if (enable_reprocheck) {
if (do_check && (n_call % interval) == 0) {
for (int thread = 0; thread < sumarray.size(); thread++) {
int words = sizeof(sumarray[thread])/sizeof(unsigned char);
unsigned char xors[words];
bitwise_xor(sumarray[thread], th_states[n_call][thread],xors);
// OR all words
unsigned char res = 0;
for (int w = 0; w < words; w++) res = res | xors[w];
Grid_unquiesce_nodes();
int rank = 0;
while (rank < grid->_Nprocessors){
if (rank == grid->ThisRank() ){
if ( res ) {
std::cout << "Reproducibility failure report" << std::endl;
grid->PrintRankInfo();
std::cout << "Call: "<< n_call << " Thread: " << thread << std::endl;
std::cout << "Size of states: " << th_states.size() << std::endl;
std::cout << std::setprecision(GRID_REAL_DIGITS+1) << std::scientific;
std::cout << "Saved partial sum : " << th_states[n_call][thread] << std::endl;
std::cout << "Current partial sum: " << sumarray[thread] << std::endl;
std::cout << "Saved state " << std::endl; show_binaryrep(th_states[n_call][thread]);
std::cout << "Current state" << std::endl; show_binaryrep(sumarray[thread]);
std::cout << "XOR result" << std::endl; show_binaryrep(xors, words);
//std::cout << std::defaultfloat; //not supported by some compilers
std::cout << std::setprecision(6);
success = false;
}
}
rank++;
grid->Barrier();
}
Grid_quiesce_nodes();
}
} else if (!do_check)
{
std::cout << GridLogDebug << "Saving thread state for inner product. Call n. "
<< n_call << std::endl;
th_states.resize(n_call+1);
th_states[n_call].resize(grid->SumArraySize());
th_states[n_call] = sumarray; // save threads state
//n_call++;
}
n_call++;
}
}
};
#ifdef GRID_WARN_SUBOPTIMAL
#warning "Optimisation alert all these reduction loops are NOT threaded "
#endif
@ -120,25 +39,12 @@ class ReproducibilityState {
// Deterministic Reduction operations
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class vobj> inline RealD norm2(const Lattice<vobj> &arg){
ReproducibilityState<vobj> repr;
ComplexD nrm = innerProduct(arg, arg, repr);
return std::real(nrm);
}
template <class vobj>
inline RealD norm2(const Lattice<vobj> &arg, ReproducibilityState<vobj>& rep) {
ComplexD nrm = innerProduct(arg, arg, rep);
return std::real(nrm);
}
ComplexD nrm = innerProduct(arg,arg);
return std::real(nrm);
}
template<class vobj>
inline ComplexD innerProduct(const Lattice<vobj> &left,const Lattice<vobj> &right){
ReproducibilityState<vobj> repr;
return innerProduct(left, right, repr);
}
template<class vobj>
inline ComplexD innerProduct(const Lattice<vobj> &left,const Lattice<vobj> &right, ReproducibilityState<vobj>& repr)
inline ComplexD innerProduct(const Lattice<vobj> &left,const Lattice<vobj> &right)
{
typedef typename vobj::scalar_type scalar_type;
typedef typename vobj::vector_type vector_type;
@ -148,28 +54,24 @@ class ReproducibilityState {
std::vector<vector_type,alignedAllocator<vector_type> > sumarray(grid->SumArraySize());
for(int i=0;i<grid->SumArraySize();i++){
sumarray[i]=zero;
sumarray[i]=zero;
}
PARALLEL_FOR_LOOP_STATIC //request statically scheduled threads for reproducibility
PARALLEL_FOR_LOOP
for(int thr=0;thr<grid->SumArraySize();thr++){
int nwork, mywork, myoff;
GridThread::GetWork(left._grid->oSites(),thr,mywork,myoff);
decltype(innerProduct(left._odata[0],right._odata[0])) vnrm = zero; // private to thread; sub summation
int nwork, mywork, myoff;
GridThread::GetWork(left._grid->oSites(),thr,mywork,myoff);
decltype(innerProduct(left._odata[0],right._odata[0])) vnrm=zero; // private to thread; sub summation
for(int ss=myoff;ss<mywork+myoff; ss++){
vnrm = vnrm + innerProduct(left._odata[ss],right._odata[ss]);
}
sumarray[thr]=TensorRemove(vnrm) ;
vnrm = vnrm + innerProduct(left._odata[ss],right._odata[ss]);
}
sumarray[thr]=TensorRemove(vnrm) ;
}
/////////// Reproducibility
repr.check(grid, sumarray);
///////////////////////////
vector_type vvnrm; vvnrm=zero; // sum across threads
for(int i=0;i<grid->SumArraySize();i++){
vvnrm = vvnrm+sumarray[i];
vvnrm = vvnrm+sumarray[i];
}
nrm = Reduce(vvnrm);// sum across simd
right._grid->GlobalSum(nrm);
@ -177,26 +79,26 @@ class ReproducibilityState {
}
template<class Op,class T1>
inline auto sum(const LatticeUnaryExpression<Op,T1> & expr)
->typename decltype(expr.first.func(eval(0,std::get<0>(expr.second))))::scalar_object
inline auto sum(const LatticeUnaryExpression<Op,T1> & expr)
->typename decltype(expr.first.func(eval(0,std::get<0>(expr.second))))::scalar_object
{
return sum(closure(expr));
}
template<class Op,class T1,class T2>
inline auto sum(const LatticeBinaryExpression<Op,T1,T2> & expr)
->typename decltype(expr.first.func(eval(0,std::get<0>(expr.second)),eval(0,std::get<1>(expr.second))))::scalar_object
inline auto sum(const LatticeBinaryExpression<Op,T1,T2> & expr)
->typename decltype(expr.first.func(eval(0,std::get<0>(expr.second)),eval(0,std::get<1>(expr.second))))::scalar_object
{
return sum(closure(expr));
}
template<class Op,class T1,class T2,class T3>
inline auto sum(const LatticeTrinaryExpression<Op,T1,T2,T3> & expr)
->typename decltype(expr.first.func(eval(0,std::get<0>(expr.second)),
eval(0,std::get<1>(expr.second)),
eval(0,std::get<2>(expr.second))
))::scalar_object
inline auto sum(const LatticeTrinaryExpression<Op,T1,T2,T3> & expr)
->typename decltype(expr.first.func(eval(0,std::get<0>(expr.second)),
eval(0,std::get<1>(expr.second)),
eval(0,std::get<2>(expr.second))
))::scalar_object
{
return sum(closure(expr));
}
@ -209,24 +111,24 @@ class ReproducibilityState {
std::vector<vobj,alignedAllocator<vobj> > sumarray(grid->SumArraySize());
for(int i=0;i<grid->SumArraySize();i++){
sumarray[i]=zero;
sumarray[i]=zero;
}
PARALLEL_FOR_LOOP
PARALLEL_FOR_LOOP
for(int thr=0;thr<grid->SumArraySize();thr++){
int nwork, mywork, myoff;
GridThread::GetWork(grid->oSites(),thr,mywork,myoff);
int nwork, mywork, myoff;
GridThread::GetWork(grid->oSites(),thr,mywork,myoff);
vobj vvsum=zero;
vobj vvsum=zero;
for(int ss=myoff;ss<mywork+myoff; ss++){
vvsum = vvsum + arg._odata[ss];
}
sumarray[thr]=vvsum;
vvsum = vvsum + arg._odata[ss];
}
sumarray[thr]=vvsum;
}
vobj vsum=zero; // sum across threads
for(int i=0;i<grid->SumArraySize();i++){
vsum = vsum+sumarray[i];
vsum = vsum+sumarray[i];
}
typedef typename vobj::scalar_object sobj;
@ -236,7 +138,7 @@ class ReproducibilityState {
extract(vsum,buf);
for(int i=0;i<Nsimd;i++) ssum = ssum + buf[i];
arg._grid->GlobalSum(ssum);
arg._grid->GlobalSum(ssum);
return ssum;
}
@ -244,23 +146,23 @@ class ReproducibilityState {
template<class vobj> inline void sliceSum(const Lattice<vobj> &Data,std::vector<typename vobj::scalar_object> &result,int orthogdim)
{
typedef typename vobj::scalar_object sobj;
GridBase *grid = Data._grid;
assert(grid!=NULL);
{
typedef typename vobj::scalar_object sobj;
GridBase *grid = Data._grid;
assert(grid!=NULL);
// FIXME
// std::cout<<GridLogMessage<<"WARNING ! SliceSum is unthreaded "<<grid->SumArraySize()<<" threads "<<std::endl;
const int Nd = grid->_ndimension;
const int Nsimd = grid->Nsimd();
const int Nd = grid->_ndimension;
const int Nsimd = grid->Nsimd();
assert(orthogdim >= 0);
assert(orthogdim < Nd);
assert(orthogdim >= 0);
assert(orthogdim < Nd);
int fd=grid->_fdimensions[orthogdim];
int ld=grid->_ldimensions[orthogdim];
int rd=grid->_rdimensions[orthogdim];
int fd=grid->_fdimensions[orthogdim];
int ld=grid->_ldimensions[orthogdim];
int rd=grid->_rdimensions[orthogdim];
std::vector<vobj,alignedAllocator<vobj> > lvSum(rd); // will locally sum vectors first
std::vector<sobj> lsSum(ld,zero); // sum across these down to scalars

View File

@ -30,6 +30,7 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
#define GRID_LATTICE_RNG_H
#include <random>
#include <Grid/sitmo_rng/sitmo_prng_engine.hpp>
namespace Grid {
@ -114,10 +115,14 @@ namespace Grid {
typedef uint64_t RngStateType;
typedef std::ranlux48 RngEngine;
static const int RngStateCount = 15;
#else
#elif RNG_MT19937
typedef std::mt19937 RngEngine;
typedef uint32_t RngStateType;
static const int RngStateCount = std::mt19937::state_size;
#elif RNG_SITMO
typedef sitmo::prng_engine RngEngine;
typedef uint64_t RngStateType;
static const int RngStateCount = 4;
#endif
std::vector<RngEngine> _generators;
std::vector<std::uniform_real_distribution<RealD>> _uniform;

View File

@ -386,6 +386,7 @@ void InsertSlice(Lattice<vobj> &lowDim,Lattice<vobj> & higherDim,int slice, int
}
// the above should guarantee that the operations are local
// Guido: check the threading here
//PARALLEL_FOR_LOOP
for(int idx=0;idx<lg->lSites();idx++){
std::vector<int> lcoor(nl);

View File

@ -14,7 +14,7 @@
#ifndef SOURCE_PUGIXML_CPP
#define SOURCE_PUGIXML_CPP
#include <pugixml/pugixml.h>
#include <Grid/pugixml/pugixml.h>
#include <stdlib.h>
#include <stdio.h>

View File

@ -29,7 +29,8 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
*************************************************************************************/
/* END LEGAL */
#include <Grid.h>
#include <Grid/Eigen/Dense>
#include <Grid/Grid.h>
namespace Grid {
@ -48,18 +49,19 @@ namespace QCD {
FourDimGrid,
FourDimRedBlackGrid,_M5,p),
mass(_mass)
{ }
{
}
template<class Impl>
void CayleyFermion5D<Impl>::Dminus(const FermionField &psi, FermionField &chi)
{
int Ls=this->Ls;
FermionField tmp(psi._grid);
this->DW(psi,tmp,DaggerNo);
FermionField tmp_f(this->FermionGrid());
this->DW(psi,tmp_f,DaggerNo);
for(int s=0;s<Ls;s++){
axpby_ssp(chi,Coeff_t(1.0),psi,-cs[s],tmp,s,s);// chi = (1-c[s] D_W) psi
axpby_ssp(chi,Coeff_t(1.0),psi,-cs[s],tmp_f,s,s);// chi = (1-c[s] D_W) psi
}
}
@ -87,8 +89,8 @@ template<class Impl> void CayleyFermion5D<Impl>::CayleyReport(void)
std::cout << GridLogMessage << "CayleyFermion5D Number of MooeeInv Calls : " << MooeeInvCalls << std::endl;
std::cout << GridLogMessage << "CayleyFermion5D ComputeTime/Calls : " << MooeeInvTime / MooeeInvCalls << " us" << std::endl;
// Flops = 9*12*Ls*vol/2
RealD mflops = 9.0*12*volume*MooeeInvCalls/MooeeInvTime/2; // 2 for red black counting
// Flops = MADD * Ls *Ls *4dvol * spin/colour/complex
RealD mflops = 2.0*24*this->Ls*volume*MooeeInvCalls/MooeeInvTime/2; // 2 for red black counting
std::cout << GridLogMessage << "Average mflops/s per call : " << mflops << std::endl;
std::cout << GridLogMessage << "Average mflops/s per call per rank : " << mflops/NP << std::endl;
}
@ -110,12 +112,12 @@ template<class Impl>
void CayleyFermion5D<Impl>::DminusDag(const FermionField &psi, FermionField &chi)
{
int Ls=this->Ls;
FermionField tmp(psi._grid);
this->DW(psi,tmp,DaggerYes);
FermionField tmp_f(this->FermionGrid());
this->DW(psi,tmp_f,DaggerYes);
for(int s=0;s<Ls;s++){
axpby_ssp(chi,Coeff_t(1.0),psi,-cs[s],tmp,s,s);// chi = (1-c[s] D_W) psi
axpby_ssp(chi,Coeff_t(1.0),psi,-cs[s],tmp_f,s,s);// chi = (1-c[s] D_W) psi
}
}
template<class Impl>
@ -138,6 +140,7 @@ void CayleyFermion5D<Impl>::Meooe5D (const FermionField &psi, FermionField &D
lower[0] =-mass*lower[0];
M5D(psi,psi,Din,lower,diag,upper);
}
// FIXME Redunant with the above routine; check this and eliminate
template<class Impl> void CayleyFermion5D<Impl>::Meo5D (const FermionField &psi, FermionField &chi)
{
int Ls=this->Ls;
@ -259,36 +262,33 @@ template<class Impl>
void CayleyFermion5D<Impl>::Meooe (const FermionField &psi, FermionField &chi)
{
int Ls=this->Ls;
FermionField tmp(psi._grid);
Meooe5D(psi,tmp);
Meooe5D(psi,this->tmp());
if ( psi.checkerboard == Odd ) {
this->DhopEO(tmp,chi,DaggerNo);
this->DhopEO(this->tmp(),chi,DaggerNo);
} else {
this->DhopOE(tmp,chi,DaggerNo);
this->DhopOE(this->tmp(),chi,DaggerNo);
}
}
template<class Impl>
void CayleyFermion5D<Impl>::MeooeDag (const FermionField &psi, FermionField &chi)
{
FermionField tmp(psi._grid);
// Apply 4d dslash
if ( psi.checkerboard == Odd ) {
this->DhopEO(psi,tmp,DaggerYes);
this->DhopEO(psi,this->tmp(),DaggerYes);
} else {
this->DhopOE(psi,tmp,DaggerYes);
this->DhopOE(psi,this->tmp(),DaggerYes);
}
MeooeDag5D(tmp,chi);
MeooeDag5D(this->tmp(),chi);
}
template<class Impl>
void CayleyFermion5D<Impl>::Mdir (const FermionField &psi, FermionField &chi,int dir,int disp){
FermionField tmp(psi._grid);
Meo5D(psi,tmp);
Meo5D(psi,this->tmp());
// Apply 4d dslash fragment
this->DhopDir(tmp,chi,dir,disp);
this->DhopDir(this->tmp(),chi,dir,disp);
}
// force terms; five routines; default to Dhop on diagonal
template<class Impl>
@ -459,9 +459,91 @@ void CayleyFermion5D<Impl>::SetCoefficientsInternal(RealD zolo_hi,std::vector<Co
for(int j=0;j<Ls-1;j++) delta_d *= cee[j]/bee[j];
dee[Ls-1] += delta_d;
}
int inv=1;
this->MooeeInternalCompute(0,inv,MatpInv,MatmInv);
this->MooeeInternalCompute(1,inv,MatpInvDag,MatmInvDag);
}
template<class Impl>
void CayleyFermion5D<Impl>::MooeeInternalCompute(int dag, int inv,
Vector<iSinglet<Simd> > & Matp,
Vector<iSinglet<Simd> > & Matm)
{
int Ls=this->Ls;
GridBase *grid = this->FermionRedBlackGrid();
int LLs = grid->_rdimensions[0];
if ( LLs == Ls ) return; // Not vectorised in 5th direction
Eigen::MatrixXcd Pplus = Eigen::MatrixXcd::Zero(Ls,Ls);
Eigen::MatrixXcd Pminus = Eigen::MatrixXcd::Zero(Ls,Ls);
for(int s=0;s<Ls;s++){
Pplus(s,s) = bee[s];
Pminus(s,s)= bee[s];
}
for(int s=0;s<Ls-1;s++){
Pminus(s,s+1) = -cee[s];
}
for(int s=0;s<Ls-1;s++){
Pplus(s+1,s) = -cee[s+1];
}
Pplus (0,Ls-1) = mass*cee[0];
Pminus(Ls-1,0) = mass*cee[Ls-1];
Eigen::MatrixXcd PplusMat ;
Eigen::MatrixXcd PminusMat;
if ( inv ) {
PplusMat =Pplus.inverse();
PminusMat=Pminus.inverse();
} else {
PplusMat =Pplus;
PminusMat=Pminus;
}
if(dag){
PplusMat.adjointInPlace();
PminusMat.adjointInPlace();
}
typedef typename SiteHalfSpinor::scalar_type scalar_type;
const int Nsimd=Simd::Nsimd();
Matp.resize(Ls*LLs);
Matm.resize(Ls*LLs);
for(int s2=0;s2<Ls;s2++){
for(int s1=0;s1<LLs;s1++){
int istride = LLs;
int ostride = 1;
Simd Vp;
Simd Vm;
scalar_type *sp = (scalar_type *)&Vp;
scalar_type *sm = (scalar_type *)&Vm;
for(int l=0;l<Nsimd;l++){
if ( switcheroo<Coeff_t>::iscomplex() ) {
sp[l] = PplusMat (l*istride+s1*ostride,s2);
sm[l] = PminusMat(l*istride+s1*ostride,s2);
} else {
// if real
scalar_type tmp;
tmp = PplusMat (l*istride+s1*ostride,s2);
sp[l] = scalar_type(tmp.real(),tmp.real());
tmp = PminusMat(l*istride+s1*ostride,s2);
sm[l] = scalar_type(tmp.real(),tmp.real());
}
}
Matp[LLs*s2+s1] = Vp;
Matm[LLs*s2+s1] = Vm;
}}
}
FermOpTemplateInstantiate(CayleyFermion5D);
GparityFermOpTemplateInstantiate(CayleyFermion5D);

View File

@ -33,6 +33,31 @@ namespace Grid {
namespace QCD {
template<typename T> struct switcheroo {
static inline int iscomplex() { return 0; }
template<class vec>
static inline vec mult(vec a, vec b) {
return real_mult(a,b);
}
};
template<> struct switcheroo<ComplexD> {
static inline int iscomplex() { return 1; }
template<class vec>
static inline vec mult(vec a, vec b) {
return a*b;
}
};
template<> struct switcheroo<ComplexF> {
static inline int iscomplex() { return 1; }
template<class vec>
static inline vec mult(vec a, vec b) {
return a*b;
}
};
template<class Impl>
class CayleyFermion5D : public WilsonFermion5D<Impl>
{
@ -75,7 +100,19 @@ namespace Grid {
std::vector<Coeff_t> &lower,
std::vector<Coeff_t> &diag,
std::vector<Coeff_t> &upper);
void MooeeInternal(const FermionField &in, FermionField &out,int dag,int inv);
void MooeeInternalCompute(int dag, int inv, Vector<iSinglet<Simd> > & Matp, Vector<iSinglet<Simd> > & Matm);
void MooeeInternalAsm(const FermionField &in, FermionField &out,
int LLs, int site,
Vector<iSinglet<Simd> > &Matp,
Vector<iSinglet<Simd> > &Matm);
void MooeeInternalZAsm(const FermionField &in, FermionField &out,
int LLs, int site,
Vector<iSinglet<Simd> > &Matp,
Vector<iSinglet<Simd> > &Matm);
virtual void Instantiatable(void)=0;
@ -112,6 +149,12 @@ namespace Grid {
std::vector<Coeff_t> ueem;
std::vector<Coeff_t> dee;
// Matrices of 5d ee inverse params
Vector<iSinglet<Simd> > MatpInv;
Vector<iSinglet<Simd> > MatmInv;
Vector<iSinglet<Simd> > MatpInvDag;
Vector<iSinglet<Simd> > MatmInvDag;
// Constructors
CayleyFermion5D(GaugeField &_Umu,
GridCartesian &FiveDimGrid,

View File

@ -29,7 +29,7 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
*************************************************************************************/
/* END LEGAL */
#include <Grid.h>
#include <Grid/Grid.h>
namespace Grid {

View File

@ -30,7 +30,7 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
/* END LEGAL */
#include <Grid/Eigen/Dense>
#include <Grid.h>
#include <Grid/Grid.h>
namespace Grid {

View File

@ -29,7 +29,7 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
*************************************************************************************/
/* END LEGAL */
#include <Grid.h>
#include <Grid/Grid.h>
namespace Grid {

View File

@ -29,13 +29,12 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
*************************************************************************************/
/* END LEGAL */
#include <Grid/Eigen/Dense>
#include <Grid.h>
#include <Grid/Grid.h>
namespace Grid {
namespace QCD {
/*
namespace QCD { /*
* Dense matrix versions of routines
*/
template<class Impl>
@ -126,7 +125,6 @@ PARALLEL_FOR_LOOP
for(int v=0;v<LLs;v++){
vprefetch(psi[ss+v+LLs]);
// vprefetch(phi[ss+v+LLs]);
int vp= (v==LLs-1) ? 0 : v+1;
int vm= (v==0 ) ? LLs-1 : v-1;
@ -145,9 +143,6 @@ PARALLEL_FOR_LOOP
Simd hm_11 = psi[ss+vm]()(1)(1);
Simd hm_12 = psi[ss+vm]()(1)(2);
// if ( ss==0) std::cout << " hp_00 " <<hp_00<<std::endl;
// if ( ss==0) std::cout << " hm_00 " <<hm_00<<std::endl;
if ( vp<=v ) {
hp_00.v = Optimization::Rotate::tRotate<2>(hp_00.v);
hp_01.v = Optimization::Rotate::tRotate<2>(hp_01.v);
@ -165,42 +160,20 @@ PARALLEL_FOR_LOOP
hm_12.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_12.v);
}
/*
if ( ss==0) std::cout << " dphi_00 " <<d[v]()()() * phi[ss+v]()(0)(0) <<std::endl;
if ( ss==0) std::cout << " dphi_10 " <<d[v]()()() * phi[ss+v]()(1)(0) <<std::endl;
if ( ss==0) std::cout << " dphi_20 " <<d[v]()()() * phi[ss+v]()(2)(0) <<std::endl;
if ( ss==0) std::cout << " dphi_30 " <<d[v]()()() * phi[ss+v]()(3)(0) <<std::endl;
*/
Simd p_00 = d[v]()()() * phi[ss+v]()(0)(0) + l[v]()()()*hm_00;
Simd p_01 = d[v]()()() * phi[ss+v]()(0)(1) + l[v]()()()*hm_01;
Simd p_02 = d[v]()()() * phi[ss+v]()(0)(2) + l[v]()()()*hm_02;
Simd p_10 = d[v]()()() * phi[ss+v]()(1)(0) + l[v]()()()*hm_10;
Simd p_11 = d[v]()()() * phi[ss+v]()(1)(1) + l[v]()()()*hm_11;
Simd p_12 = d[v]()()() * phi[ss+v]()(1)(2) + l[v]()()()*hm_12;
Simd p_20 = d[v]()()() * phi[ss+v]()(2)(0) + u[v]()()()*hp_00;
Simd p_21 = d[v]()()() * phi[ss+v]()(2)(1) + u[v]()()()*hp_01;
Simd p_22 = d[v]()()() * phi[ss+v]()(2)(2) + u[v]()()()*hp_02;
Simd p_30 = d[v]()()() * phi[ss+v]()(3)(0) + u[v]()()()*hp_10;
Simd p_31 = d[v]()()() * phi[ss+v]()(3)(1) + u[v]()()()*hp_11;
Simd p_32 = d[v]()()() * phi[ss+v]()(3)(2) + u[v]()()()*hp_12;
// Can force these to real arithmetic and save 2x.
Simd p_00 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(),hm_00);
Simd p_01 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(),hm_01);
Simd p_02 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(),hm_02);
Simd p_10 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(),hm_10);
Simd p_11 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(),hm_11);
Simd p_12 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(),hm_12);
Simd p_20 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(),hp_00);
Simd p_21 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(),hp_01);
Simd p_22 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(),hp_02);
Simd p_30 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(),hp_10);
Simd p_31 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(),hp_11);
Simd p_32 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(),hp_12);
// if ( ss==0){
/*
std::cout << ss<<" "<< v<< " good "<< chi[ss+v]()(0)(0) << " bad "<<p_00<<" diff "<<chi[ss+v]()(0)(0)-p_00<<std::endl;
std::cout << ss<<" "<< v<< " good "<< chi[ss+v]()(0)(1) << " bad "<<p_01<<" diff "<<chi[ss+v]()(0)(1)-p_01<<std::endl;
std::cout << ss<<" "<< v<< " good "<< chi[ss+v]()(0)(2) << " bad "<<p_02<<" diff "<<chi[ss+v]()(0)(2)-p_02<<std::endl;
std::cout << ss<<" "<< v<< " good "<< chi[ss+v]()(1)(0) << " bad "<<p_10<<" diff "<<chi[ss+v]()(1)(0)-p_10<<std::endl;
std::cout << ss<<" "<< v<< " good "<< chi[ss+v]()(1)(1) << " bad "<<p_11<<" diff "<<chi[ss+v]()(1)(1)-p_11<<std::endl;
std::cout << ss<<" "<< v<< " good "<< chi[ss+v]()(1)(2) << " bad "<<p_12<<" diff "<<chi[ss+v]()(1)(2)-p_12<<std::endl;
std::cout << ss<<" "<< v<< " good "<< chi[ss+v]()(2)(0) << " bad "<<p_20<<" diff "<<chi[ss+v]()(2)(0)-p_20<<std::endl;
std::cout << ss<<" "<< v<< " good "<< chi[ss+v]()(2)(1) << " bad "<<p_21<<" diff "<<chi[ss+v]()(2)(1)-p_21<<std::endl;
std::cout << ss<<" "<< v<< " good "<< chi[ss+v]()(2)(2) << " bad "<<p_22<<" diff "<<chi[ss+v]()(2)(2)-p_22<<std::endl;
std::cout << ss<<" "<< v<< " good "<< chi[ss+v]()(3)(0) << " bad "<<p_30<<" diff "<<chi[ss+v]()(3)(0)-p_30<<std::endl;
std::cout << ss<<" "<< v<< " good "<< chi[ss+v]()(3)(1) << " bad "<<p_31<<" diff "<<chi[ss+v]()(3)(1)-p_31<<std::endl;
std::cout << ss<<" "<< v<< " good "<< chi[ss+v]()(3)(2) << " bad "<<p_32<<" diff "<<chi[ss+v]()(3)(2)-p_32<<std::endl;
}
*/
vstream(chi[ss+v]()(0)(0),p_00);
vstream(chi[ss+v]()(0)(1),p_01);
vstream(chi[ss+v]()(0)(2),p_02);
@ -261,7 +234,7 @@ void CayleyFermion5D<Impl>::M5Ddag(const FermionField &psi,
M5Dtime-=usecond();
PARALLEL_FOR_LOOP
for(int ss=0;ss<grid->oSites();ss+=LLs){ // adds LLs
#if 0
alignas(64) SiteHalfSpinor hp;
alignas(64) SiteHalfSpinor hm;
alignas(64) SiteSpinor fp;
@ -287,9 +260,504 @@ PARALLEL_FOR_LOOP
chi[ss+v] = chi[ss+v] +l[v]*fm;
}
#else
for(int v=0;v<LLs;v++){
vprefetch(psi[ss+v+LLs]);
int vp= (v==LLs-1) ? 0 : v+1;
int vm= (v==0 ) ? LLs-1 : v-1;
Simd hp_00 = psi[ss+vp]()(0)(0);
Simd hp_01 = psi[ss+vp]()(0)(1);
Simd hp_02 = psi[ss+vp]()(0)(2);
Simd hp_10 = psi[ss+vp]()(1)(0);
Simd hp_11 = psi[ss+vp]()(1)(1);
Simd hp_12 = psi[ss+vp]()(1)(2);
Simd hm_00 = psi[ss+vm]()(2)(0);
Simd hm_01 = psi[ss+vm]()(2)(1);
Simd hm_02 = psi[ss+vm]()(2)(2);
Simd hm_10 = psi[ss+vm]()(3)(0);
Simd hm_11 = psi[ss+vm]()(3)(1);
Simd hm_12 = psi[ss+vm]()(3)(2);
if ( vp<=v ) {
hp_00.v = Optimization::Rotate::tRotate<2>(hp_00.v);
hp_01.v = Optimization::Rotate::tRotate<2>(hp_01.v);
hp_02.v = Optimization::Rotate::tRotate<2>(hp_02.v);
hp_10.v = Optimization::Rotate::tRotate<2>(hp_10.v);
hp_11.v = Optimization::Rotate::tRotate<2>(hp_11.v);
hp_12.v = Optimization::Rotate::tRotate<2>(hp_12.v);
}
if ( vm>=v ) {
hm_00.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_00.v);
hm_01.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_01.v);
hm_02.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_02.v);
hm_10.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_10.v);
hm_11.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_11.v);
hm_12.v = Optimization::Rotate::tRotate<2*Simd::Nsimd()-2>(hm_12.v);
}
Simd p_00 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(),hp_00);
Simd p_01 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(),hp_01);
Simd p_02 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(0)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(),hp_02);
Simd p_10 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(0)) + switcheroo<Coeff_t>::mult(u[v]()()(),hp_10);
Simd p_11 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(1)) + switcheroo<Coeff_t>::mult(u[v]()()(),hp_11);
Simd p_12 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(1)(2)) + switcheroo<Coeff_t>::mult(u[v]()()(),hp_12);
Simd p_20 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(),hm_00);
Simd p_21 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(),hm_01);
Simd p_22 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(2)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(),hm_02);
Simd p_30 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(0)) + switcheroo<Coeff_t>::mult(l[v]()()(),hm_10);
Simd p_31 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(1)) + switcheroo<Coeff_t>::mult(l[v]()()(),hm_11);
Simd p_32 = switcheroo<Coeff_t>::mult(d[v]()()(), phi[ss+v]()(3)(2)) + switcheroo<Coeff_t>::mult(l[v]()()(),hm_12);
vstream(chi[ss+v]()(0)(0),p_00);
vstream(chi[ss+v]()(0)(1),p_01);
vstream(chi[ss+v]()(0)(2),p_02);
vstream(chi[ss+v]()(1)(0),p_10);
vstream(chi[ss+v]()(1)(1),p_11);
vstream(chi[ss+v]()(1)(2),p_12);
vstream(chi[ss+v]()(2)(0),p_20);
vstream(chi[ss+v]()(2)(1),p_21);
vstream(chi[ss+v]()(2)(2),p_22);
vstream(chi[ss+v]()(3)(0),p_30);
vstream(chi[ss+v]()(3)(1),p_31);
vstream(chi[ss+v]()(3)(2),p_32);
}
#endif
}
M5Dtime+=usecond();
}
#ifdef AVX512
#include <simd/Intel512common.h>
#include <simd/Intel512avx.h>
#include <simd/Intel512single.h>
#endif
template<class Impl>
void CayleyFermion5D<Impl>::MooeeInternalAsm(const FermionField &psi, FermionField &chi,
int LLs, int site,
Vector<iSinglet<Simd> > &Matp,
Vector<iSinglet<Simd> > &Matm)
{
#ifndef AVX512
{
SiteHalfSpinor BcastP;
SiteHalfSpinor BcastM;
SiteHalfSpinor SiteChiP;
SiteHalfSpinor SiteChiM;
// Ls*Ls * 2 * 12 * vol flops
for(int s1=0;s1<LLs;s1++){
for(int s2=0;s2<LLs;s2++){
for(int l=0; l<Simd::Nsimd();l++){ // simd lane
int s=s2+l*LLs;
int lex=s2+LLs*site;
if ( s2==0 && l==0) {
SiteChiP=zero;
SiteChiM=zero;
}
for(int sp=0;sp<2;sp++){
for(int co=0;co<Nc;co++){
vbroadcast(BcastP()(sp )(co),psi[lex]()(sp)(co),l);
}}
for(int sp=0;sp<2;sp++){
for(int co=0;co<Nc;co++){
vbroadcast(BcastM()(sp )(co),psi[lex]()(sp+2)(co),l);
}}
for(int sp=0;sp<2;sp++){
for(int co=0;co<Nc;co++){
SiteChiP()(sp)(co)=real_madd(Matp[LLs*s+s1]()()(),BcastP()(sp)(co),SiteChiP()(sp)(co)); // 1100 us.
SiteChiM()(sp)(co)=real_madd(Matm[LLs*s+s1]()()(),BcastM()(sp)(co),SiteChiM()(sp)(co)); // each found by commenting out
}}
}}
{
int lex = s1+LLs*site;
for(int sp=0;sp<2;sp++){
for(int co=0;co<Nc;co++){
vstream(chi[lex]()(sp)(co), SiteChiP()(sp)(co));
vstream(chi[lex]()(sp+2)(co), SiteChiM()(sp)(co));
}}
}
}
}
#else
{
// pointers
// MASK_REGS;
#define Chi_00 %%zmm1
#define Chi_01 %%zmm2
#define Chi_02 %%zmm3
#define Chi_10 %%zmm4
#define Chi_11 %%zmm5
#define Chi_12 %%zmm6
#define Chi_20 %%zmm7
#define Chi_21 %%zmm8
#define Chi_22 %%zmm9
#define Chi_30 %%zmm10
#define Chi_31 %%zmm11
#define Chi_32 %%zmm12
#define BCAST0 %%zmm13
#define BCAST1 %%zmm14
#define BCAST2 %%zmm15
#define BCAST3 %%zmm16
#define BCAST4 %%zmm17
#define BCAST5 %%zmm18
#define BCAST6 %%zmm19
#define BCAST7 %%zmm20
#define BCAST8 %%zmm21
#define BCAST9 %%zmm22
#define BCAST10 %%zmm23
#define BCAST11 %%zmm24
int incr=LLs*LLs*sizeof(iSinglet<Simd>);
for(int s1=0;s1<LLs;s1++){
for(int s2=0;s2<LLs;s2++){
int lex=s2+LLs*site;
uint64_t a0 = (uint64_t)&Matp[LLs*s2+s1]; // should be cacheable
uint64_t a1 = (uint64_t)&Matm[LLs*s2+s1];
uint64_t a2 = (uint64_t)&psi[lex];
for(int l=0; l<Simd::Nsimd();l++){ // simd lane
if ( (s2+l)==0 ) {
asm (
VPREFETCH1(0,%2) VPREFETCH1(0,%1)
VPREFETCH1(12,%2) VPREFETCH1(13,%2)
VPREFETCH1(14,%2) VPREFETCH1(15,%2)
VBCASTCDUP(0,%2,BCAST0)
VBCASTCDUP(1,%2,BCAST1)
VBCASTCDUP(2,%2,BCAST2)
VBCASTCDUP(3,%2,BCAST3)
VBCASTCDUP(4,%2,BCAST4) VMULMEM (0,%0,BCAST0,Chi_00)
VBCASTCDUP(5,%2,BCAST5) VMULMEM (0,%0,BCAST1,Chi_01)
VBCASTCDUP(6,%2,BCAST6) VMULMEM (0,%0,BCAST2,Chi_02)
VBCASTCDUP(7,%2,BCAST7) VMULMEM (0,%0,BCAST3,Chi_10)
VBCASTCDUP(8,%2,BCAST8) VMULMEM (0,%0,BCAST4,Chi_11)
VBCASTCDUP(9,%2,BCAST9) VMULMEM (0,%0,BCAST5,Chi_12)
VBCASTCDUP(10,%2,BCAST10) VMULMEM (0,%1,BCAST6,Chi_20)
VBCASTCDUP(11,%2,BCAST11) VMULMEM (0,%1,BCAST7,Chi_21)
VMULMEM (0,%1,BCAST8,Chi_22)
VMULMEM (0,%1,BCAST9,Chi_30)
VMULMEM (0,%1,BCAST10,Chi_31)
VMULMEM (0,%1,BCAST11,Chi_32)
: : "r" (a0), "r" (a1), "r" (a2) );
} else {
asm (
VBCASTCDUP(0,%2,BCAST0) VMADDMEM (0,%0,BCAST0,Chi_00)
VBCASTCDUP(1,%2,BCAST1) VMADDMEM (0,%0,BCAST1,Chi_01)
VBCASTCDUP(2,%2,BCAST2) VMADDMEM (0,%0,BCAST2,Chi_02)
VBCASTCDUP(3,%2,BCAST3) VMADDMEM (0,%0,BCAST3,Chi_10)
VBCASTCDUP(4,%2,BCAST4) VMADDMEM (0,%0,BCAST4,Chi_11)
VBCASTCDUP(5,%2,BCAST5) VMADDMEM (0,%0,BCAST5,Chi_12)
VBCASTCDUP(6,%2,BCAST6) VMADDMEM (0,%1,BCAST6,Chi_20)
VBCASTCDUP(7,%2,BCAST7) VMADDMEM (0,%1,BCAST7,Chi_21)
VBCASTCDUP(8,%2,BCAST8) VMADDMEM (0,%1,BCAST8,Chi_22)
VBCASTCDUP(9,%2,BCAST9) VMADDMEM (0,%1,BCAST9,Chi_30)
VBCASTCDUP(10,%2,BCAST10) VMADDMEM (0,%1,BCAST10,Chi_31)
VBCASTCDUP(11,%2,BCAST11) VMADDMEM (0,%1,BCAST11,Chi_32)
: : "r" (a0), "r" (a1), "r" (a2) );
}
a0 = a0+incr;
a1 = a1+incr;
a2 = a2+sizeof(Simd::scalar_type);
}}
{
int lexa = s1+LLs*site;
asm (
VSTORE(0,%0,Chi_00) VSTORE(1 ,%0,Chi_01) VSTORE(2 ,%0,Chi_02)
VSTORE(3,%0,Chi_10) VSTORE(4 ,%0,Chi_11) VSTORE(5 ,%0,Chi_12)
VSTORE(6,%0,Chi_20) VSTORE(7 ,%0,Chi_21) VSTORE(8 ,%0,Chi_22)
VSTORE(9,%0,Chi_30) VSTORE(10,%0,Chi_31) VSTORE(11,%0,Chi_32)
: : "r" ((uint64_t)&chi[lexa]) : "memory" );
}
}
}
#undef Chi_00
#undef Chi_01
#undef Chi_02
#undef Chi_10
#undef Chi_11
#undef Chi_12
#undef Chi_20
#undef Chi_21
#undef Chi_22
#undef Chi_30
#undef Chi_31
#undef Chi_32
#undef BCAST0
#undef BCAST1
#undef BCAST2
#undef BCAST3
#undef BCAST4
#undef BCAST5
#undef BCAST6
#undef BCAST7
#undef BCAST8
#undef BCAST9
#undef BCAST10
#undef BCAST11
#endif
};
// Z-mobius version
template<class Impl>
void CayleyFermion5D<Impl>::MooeeInternalZAsm(const FermionField &psi, FermionField &chi,
int LLs, int site, Vector<iSinglet<Simd> > &Matp, Vector<iSinglet<Simd> > &Matm)
{
#ifndef AVX512
{
SiteHalfSpinor BcastP;
SiteHalfSpinor BcastM;
SiteHalfSpinor SiteChiP;
SiteHalfSpinor SiteChiM;
// Ls*Ls * 2 * 12 * vol flops
for(int s1=0;s1<LLs;s1++){
for(int s2=0;s2<LLs;s2++){
for(int l=0; l<Simd::Nsimd();l++){ // simd lane
int s=s2+l*LLs;
int lex=s2+LLs*site;
if ( s2==0 && l==0) {
SiteChiP=zero;
SiteChiM=zero;
}
for(int sp=0;sp<2;sp++){
for(int co=0;co<Nc;co++){
vbroadcast(BcastP()(sp )(co),psi[lex]()(sp)(co),l);
}}
for(int sp=0;sp<2;sp++){
for(int co=0;co<Nc;co++){
vbroadcast(BcastM()(sp )(co),psi[lex]()(sp+2)(co),l);
}}
for(int sp=0;sp<2;sp++){
for(int co=0;co<Nc;co++){
SiteChiP()(sp)(co)=SiteChiP()(sp)(co)+ Matp[LLs*s+s1]()()()*BcastP()(sp)(co);
SiteChiM()(sp)(co)=SiteChiM()(sp)(co)+ Matm[LLs*s+s1]()()()*BcastM()(sp)(co);
}}
}}
{
int lex = s1+LLs*site;
for(int sp=0;sp<2;sp++){
for(int co=0;co<Nc;co++){
vstream(chi[lex]()(sp)(co), SiteChiP()(sp)(co));
vstream(chi[lex]()(sp+2)(co), SiteChiM()(sp)(co));
}}
}
}
}
#else
{
// pointers
// MASK_REGS;
#define Chi_00 %zmm0
#define Chi_01 %zmm1
#define Chi_02 %zmm2
#define Chi_10 %zmm3
#define Chi_11 %zmm4
#define Chi_12 %zmm5
#define Chi_20 %zmm6
#define Chi_21 %zmm7
#define Chi_22 %zmm8
#define Chi_30 %zmm9
#define Chi_31 %zmm10
#define Chi_32 %zmm11
#define pChi_00 %%zmm0
#define pChi_01 %%zmm1
#define pChi_02 %%zmm2
#define pChi_10 %%zmm3
#define pChi_11 %%zmm4
#define pChi_12 %%zmm5
#define pChi_20 %%zmm6
#define pChi_21 %%zmm7
#define pChi_22 %%zmm8
#define pChi_30 %%zmm9
#define pChi_31 %%zmm10
#define pChi_32 %%zmm11
#define BCAST_00 %zmm12
#define SHUF_00 %zmm13
#define BCAST_01 %zmm14
#define SHUF_01 %zmm15
#define BCAST_02 %zmm16
#define SHUF_02 %zmm17
#define BCAST_10 %zmm18
#define SHUF_10 %zmm19
#define BCAST_11 %zmm20
#define SHUF_11 %zmm21
#define BCAST_12 %zmm22
#define SHUF_12 %zmm23
#define Mp %zmm24
#define Mps %zmm25
#define Mm %zmm26
#define Mms %zmm27
#define N 8
int incr=LLs*LLs*sizeof(iSinglet<Simd>);
for(int s1=0;s1<LLs;s1++){
for(int s2=0;s2<LLs;s2++){
int lex=s2+LLs*site;
uint64_t a0 = (uint64_t)&Matp[LLs*s2+s1]; // should be cacheable
uint64_t a1 = (uint64_t)&Matm[LLs*s2+s1];
uint64_t a2 = (uint64_t)&psi[lex];
for(int l=0; l<Simd::Nsimd();l++){ // simd lane
if ( (s2+l)==0 ) {
LOAD64(%r8,a0);
LOAD64(%r9,a1);
LOAD64(%r10,a2);
asm (
VLOAD(0,%r8,Mp)// i r
VLOAD(0,%r9,Mm)
VSHUF(Mp,Mps) // r i
VSHUF(Mm,Mms)
VPREFETCH1(12,%r10) VPREFETCH1(13,%r10)
VPREFETCH1(14,%r10) VPREFETCH1(15,%r10)
VMULIDUP(0*N,%r10,Mps,Chi_00)
VMULIDUP(1*N,%r10,Mps,Chi_01)
VMULIDUP(2*N,%r10,Mps,Chi_02)
VMULIDUP(3*N,%r10,Mps,Chi_10)
VMULIDUP(4*N,%r10,Mps,Chi_11)
VMULIDUP(5*N,%r10,Mps,Chi_12)
VMULIDUP(6*N ,%r10,Mms,Chi_20)
VMULIDUP(7*N ,%r10,Mms,Chi_21)
VMULIDUP(8*N ,%r10,Mms,Chi_22)
VMULIDUP(9*N ,%r10,Mms,Chi_30)
VMULIDUP(10*N,%r10,Mms,Chi_31)
VMULIDUP(11*N,%r10,Mms,Chi_32)
VMADDSUBRDUP(0*N,%r10,Mp,Chi_00)
VMADDSUBRDUP(1*N,%r10,Mp,Chi_01)
VMADDSUBRDUP(2*N,%r10,Mp,Chi_02)
VMADDSUBRDUP(3*N,%r10,Mp,Chi_10)
VMADDSUBRDUP(4*N,%r10,Mp,Chi_11)
VMADDSUBRDUP(5*N,%r10,Mp,Chi_12)
VMADDSUBRDUP(6*N ,%r10,Mm,Chi_20)
VMADDSUBRDUP(7*N ,%r10,Mm,Chi_21)
VMADDSUBRDUP(8*N ,%r10,Mm,Chi_22)
VMADDSUBRDUP(9*N ,%r10,Mm,Chi_30)
VMADDSUBRDUP(10*N,%r10,Mm,Chi_31)
VMADDSUBRDUP(11*N,%r10,Mm,Chi_32)
);
} else {
LOAD64(%r8,a0);
LOAD64(%r9,a1);
LOAD64(%r10,a2);
asm (
VLOAD(0,%r8,Mp)
VSHUF(Mp,Mps)
VLOAD(0,%r9,Mm)
VSHUF(Mm,Mms)
VMADDSUBIDUP(0*N,%r10,Mps,Chi_00) // Mri * Pii +- Cir
VMADDSUBIDUP(1*N,%r10,Mps,Chi_01)
VMADDSUBIDUP(2*N,%r10,Mps,Chi_02)
VMADDSUBIDUP(3*N,%r10,Mps,Chi_10)
VMADDSUBIDUP(4*N,%r10,Mps,Chi_11)
VMADDSUBIDUP(5*N,%r10,Mps,Chi_12)
VMADDSUBIDUP(6 *N,%r10,Mms,Chi_20)
VMADDSUBIDUP(7 *N,%r10,Mms,Chi_21)
VMADDSUBIDUP(8 *N,%r10,Mms,Chi_22)
VMADDSUBIDUP(9 *N,%r10,Mms,Chi_30)
VMADDSUBIDUP(10*N,%r10,Mms,Chi_31)
VMADDSUBIDUP(11*N,%r10,Mms,Chi_32)
VMADDSUBRDUP(0*N,%r10,Mp,Chi_00) // Cir = Mir * Prr +- ( Mri * Pii +- Cir)
VMADDSUBRDUP(1*N,%r10,Mp,Chi_01) // Ci = MiPr + Ci + MrPi ; Cr = MrPr - ( MiPi - Cr)
VMADDSUBRDUP(2*N,%r10,Mp,Chi_02)
VMADDSUBRDUP(3*N,%r10,Mp,Chi_10)
VMADDSUBRDUP(4*N,%r10,Mp,Chi_11)
VMADDSUBRDUP(5*N,%r10,Mp,Chi_12)
VMADDSUBRDUP(6 *N,%r10,Mm,Chi_20)
VMADDSUBRDUP(7 *N,%r10,Mm,Chi_21)
VMADDSUBRDUP(8 *N,%r10,Mm,Chi_22)
VMADDSUBRDUP(9 *N,%r10,Mm,Chi_30)
VMADDSUBRDUP(10*N,%r10,Mm,Chi_31)
VMADDSUBRDUP(11*N,%r10,Mm,Chi_32)
);
}
a0 = a0+incr;
a1 = a1+incr;
a2 = a2+sizeof(Simd::scalar_type);
}}
{
int lexa = s1+LLs*site;
/*
SiteSpinor tmp;
asm (
VSTORE(0,%0,pChi_00) VSTORE(1 ,%0,pChi_01) VSTORE(2 ,%0,pChi_02)
VSTORE(3,%0,pChi_10) VSTORE(4 ,%0,pChi_11) VSTORE(5 ,%0,pChi_12)
VSTORE(6,%0,pChi_20) VSTORE(7 ,%0,pChi_21) VSTORE(8 ,%0,pChi_22)
VSTORE(9,%0,pChi_30) VSTORE(10,%0,pChi_31) VSTORE(11,%0,pChi_32)
: : "r" ((uint64_t)&tmp) : "memory" );
*/
asm (
VSTORE(0,%0,pChi_00) VSTORE(1 ,%0,pChi_01) VSTORE(2 ,%0,pChi_02)
VSTORE(3,%0,pChi_10) VSTORE(4 ,%0,pChi_11) VSTORE(5 ,%0,pChi_12)
VSTORE(6,%0,pChi_20) VSTORE(7 ,%0,pChi_21) VSTORE(8 ,%0,pChi_22)
VSTORE(9,%0,pChi_30) VSTORE(10,%0,pChi_31) VSTORE(11,%0,pChi_32)
: : "r" ((uint64_t)&chi[lexa]) : "memory" );
// if ( 1 || (site==0) ) {
// std::cout<<site << " s1 "<<s1<<"\n\t"<<tmp << "\n't" << chi[lexa] <<"\n\t"<<tmp-chi[lexa]<<std::endl;
// }
}
}
}
#undef Chi_00
#undef Chi_01
#undef Chi_02
#undef Chi_10
#undef Chi_11
#undef Chi_12
#undef Chi_20
#undef Chi_21
#undef Chi_22
#undef Chi_30
#undef Chi_31
#undef Chi_32
#undef BCAST0
#undef BCAST1
#undef BCAST2
#undef BCAST3
#undef BCAST4
#undef BCAST5
#undef BCAST6
#undef BCAST7
#undef BCAST8
#undef BCAST9
#undef BCAST10
#undef BCAST11
#endif
};
template<class Impl>
void CayleyFermion5D<Impl>::MooeeInternal(const FermionField &psi, FermionField &chi,int dag, int inv)
{
@ -299,108 +767,41 @@ void CayleyFermion5D<Impl>::MooeeInternal(const FermionField &psi, FermionField
chi.checkerboard=psi.checkerboard;
Eigen::MatrixXcd Pplus = Eigen::MatrixXcd::Zero(Ls,Ls);
Eigen::MatrixXcd Pminus = Eigen::MatrixXcd::Zero(Ls,Ls);
Vector<iSinglet<Simd> > Matp;
Vector<iSinglet<Simd> > Matm;
Vector<iSinglet<Simd> > *_Matp;
Vector<iSinglet<Simd> > *_Matm;
for(int s=0;s<Ls;s++){
Pplus(s,s) = bee[s];
Pminus(s,s)= bee[s];
// MooeeInternalCompute(dag,inv,Matp,Matm);
if ( inv && dag ) {
_Matp = &MatpInvDag;
_Matm = &MatmInvDag;
}
for(int s=0;s<Ls-1;s++){
Pminus(s,s+1) = -cee[s];
if ( inv && (!dag) ) {
_Matp = &MatpInv;
_Matm = &MatmInv;
}
if ( !inv ) {
MooeeInternalCompute(dag,inv,Matp,Matm);
_Matp = &Matp;
_Matm = &Matm;
}
for(int s=0;s<Ls-1;s++){
Pplus(s+1,s) = -cee[s+1];
}
Pplus (0,Ls-1) = mass*cee[0];
Pminus(Ls-1,0) = mass*cee[Ls-1];
Eigen::MatrixXcd PplusMat ;
Eigen::MatrixXcd PminusMat;
if ( inv ) {
PplusMat =Pplus.inverse();
PminusMat=Pminus.inverse();
} else {
PplusMat =Pplus;
PminusMat=Pminus;
}
if(dag){
PplusMat.adjointInPlace();
PminusMat.adjointInPlace();
}
typedef typename SiteHalfSpinor::scalar_type scalar_type;
const int Nsimd=Simd::Nsimd();
Vector<iSinglet<Simd> > Matp(Ls*LLs);
Vector<iSinglet<Simd> > Matm(Ls*LLs);
assert(_Matp->size()==Ls*LLs);
for(int s2=0;s2<Ls;s2++){
for(int s1=0;s1<LLs;s1++){
int istride = LLs;
int ostride = 1;
Simd Vp;
Simd Vm;
scalar_type *sp = (scalar_type *)&Vp;
scalar_type *sm = (scalar_type *)&Vm;
for(int l=0;l<Nsimd;l++){
sp[l] = PplusMat (l*istride+s1*ostride ,s2);
sm[l] = PminusMat(l*istride+s1*ostride,s2);
}
Matp[LLs*s2+s1] = Vp;
Matm[LLs*s2+s1] = Vm;
}
}
MooeeInvCalls++;
MooeeInvTime-=usecond();
// Dynamic allocate on stack to get per thread without serialised heap acces
#pragma omp parallel
{
Vector<SiteHalfSpinor> SitePplus(LLs);
Vector<SiteHalfSpinor> SitePminus(LLs);
Vector<SiteHalfSpinor> SiteChiP(LLs);
Vector<SiteHalfSpinor> SiteChiM(LLs);
Vector<SiteSpinor> SiteChi(LLs);
SiteHalfSpinor BcastP;
SiteHalfSpinor BcastM;
#pragma omp for
for(auto site=0;site<vol;site++){
for(int s=0;s<LLs;s++){
int lex = s+LLs*site;
spProj5p(SitePplus[s] ,psi[lex]);
spProj5m(SitePminus[s],psi[lex]);
SiteChiP[s]=zero;
SiteChiM[s]=zero;
if ( switcheroo<Coeff_t>::iscomplex() ) {
PARALLEL_FOR_LOOP
for(auto site=0;site<vol;site++){
MooeeInternalZAsm(psi,chi,LLs,site,*_Matp,*_Matm);
}
int s=0;
for(int l=0; l<Simd::Nsimd();l++){ // simd lane
for(int s2=0;s2<LLs;s2++){ // Column loop of right hand side
vbroadcast(BcastP,SitePplus [s2],l);
vbroadcast(BcastM,SitePminus[s2],l);
for(int s1=0;s1<LLs;s1++){ // Column loop of reduction variables
SiteChiP[s1]=SiteChiP[s1]+Matp[LLs*s+s1]*BcastP;
SiteChiM[s1]=SiteChiM[s1]+Matm[LLs*s+s1]*BcastM;
}
s++;
}}
for(int s=0;s<LLs;s++){
int lex = s+LLs*site;
spRecon5p(SiteChi[s],SiteChiP[s]);
accumRecon5m(SiteChi[s],SiteChiM[s]);
chi[lex] = SiteChi[s]*0.5;
} else {
PARALLEL_FOR_LOOP
for(auto site=0;site<vol;site++){
MooeeInternalAsm(psi,chi,LLs,site,*_Matp,*_Matm);
}
}
}
MooeeInvTime+=usecond();
}
@ -414,4 +815,5 @@ template void CayleyFermion5D<DomainWallVec5dImplD>::MooeeInternal(const Fermion
template void CayleyFermion5D<ZDomainWallVec5dImplF>::MooeeInternal(const FermionField &psi, FermionField &chi,int dag, int inv);
template void CayleyFermion5D<ZDomainWallVec5dImplD>::MooeeInternal(const FermionField &psi, FermionField &chi,int dag, int inv);
}}

View File

@ -26,7 +26,7 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include <Grid.h>
#include <Grid/Grid.h>
namespace Grid {
namespace QCD {

View File

@ -48,6 +48,8 @@ namespace Grid {
FermionOperator(const ImplParams &p= ImplParams()) : Impl(p) {};
virtual FermionField &tmp(void) = 0;
GridBase * Grid(void) { return FermionGrid(); }; // this is all the linalg routines need to know
GridBase * RedBlackGrid(void) { return FermionRedBlackGrid(); };

View File

@ -48,8 +48,10 @@ namespace QCD {
// typedef typename XXX GaugeField;
// typedef typename XXX GaugeActField;
// typedef typename XXX FermionField;
// typedef typename XXX PropagatorField;
// typedef typename XXX DoubledGaugeField;
// typedef typename XXX SiteSpinor;
// typedef typename XXX SitePropagator;
// typedef typename XXX SiteHalfSpinor;
// typedef typename XXX Compressor;
//
@ -95,13 +97,15 @@ namespace QCD {
#define INHERIT_FIMPL_TYPES(Impl)\
typedef typename Impl::FermionField FermionField; \
typedef typename Impl::PropagatorField PropagatorField; \
typedef typename Impl::DoubledGaugeField DoubledGaugeField; \
typedef typename Impl::SiteSpinor SiteSpinor; \
typedef typename Impl::SitePropagator SitePropagator; \
typedef typename Impl::SiteHalfSpinor SiteHalfSpinor; \
typedef typename Impl::Compressor Compressor; \
typedef typename Impl::StencilImpl StencilImpl; \
typedef typename Impl::ImplParams ImplParams; \
typedef typename Impl::Coeff_t Coeff_t;
typedef typename Impl::ImplParams ImplParams; \
typedef typename Impl::Coeff_t Coeff_t; \
#define INHERIT_IMPL_TYPES(Base) \
INHERIT_GIMPL_TYPES(Base) \
@ -127,14 +131,17 @@ namespace QCD {
INHERIT_GIMPL_TYPES(Gimpl);
template <typename vtype> using iImplSpinor = iScalar<iVector<iVector<vtype, Dimension>, Ns> >;
template <typename vtype> using iImplPropagator = iScalar<iMatrix<iMatrix<vtype, Dimension>, Ns> >;
template <typename vtype> using iImplHalfSpinor = iScalar<iVector<iVector<vtype, Dimension>, Nhs> >;
template <typename vtype> using iImplDoubledGaugeField = iVector<iScalar<iMatrix<vtype, Dimension> >, Nds>;
typedef iImplSpinor<Simd> SiteSpinor;
typedef iImplPropagator<Simd> SitePropagator;
typedef iImplHalfSpinor<Simd> SiteHalfSpinor;
typedef iImplDoubledGaugeField<Simd> SiteDoubledGaugeField;
typedef Lattice<SiteSpinor> FermionField;
typedef Lattice<SitePropagator> PropagatorField;
typedef Lattice<SiteDoubledGaugeField> DoubledGaugeField;
typedef WilsonCompressor<SiteHalfSpinor, SiteSpinor> Compressor;
@ -216,14 +223,17 @@ class DomainWallVec5dImpl : public PeriodicGaugeImpl< GaugeImplTypes< S,Nrepres
INHERIT_GIMPL_TYPES(Gimpl);
template <typename vtype> using iImplSpinor = iScalar<iVector<iVector<vtype, Nrepresentation>, Ns> >;
template <typename vtype> using iImplPropagator = iScalar<iMatrix<iMatrix<vtype, Nrepresentation>, Ns> >;
template <typename vtype> using iImplHalfSpinor = iScalar<iVector<iVector<vtype, Nrepresentation>, Nhs> >;
template <typename vtype> using iImplDoubledGaugeField = iVector<iScalar<iMatrix<vtype, Nrepresentation> >, Nds>;
template <typename vtype> using iImplGaugeField = iVector<iScalar<iMatrix<vtype, Nrepresentation> >, Nd>;
template <typename vtype> using iImplGaugeLink = iScalar<iScalar<iMatrix<vtype, Nrepresentation> > >;
typedef iImplSpinor<Simd> SiteSpinor;
typedef iImplPropagator<Simd> SitePropagator;
typedef iImplHalfSpinor<Simd> SiteHalfSpinor;
typedef Lattice<SiteSpinor> FermionField;
typedef Lattice<SitePropagator> PropagatorField;
// Make the doubled gauge field a *scalar*
typedef iImplDoubledGaugeField<typename Simd::scalar_type> SiteDoubledGaugeField; // This is a scalar
@ -315,14 +325,17 @@ class GparityWilsonImpl : public ConjugateGaugeImpl<GaugeImplTypes<S, Nrepresent
INHERIT_GIMPL_TYPES(Gimpl);
template <typename vtype> using iImplSpinor = iVector<iVector<iVector<vtype, Nrepresentation>, Ns>, Ngp>;
template <typename vtype> using iImplPropagator = iVector<iMatrix<iMatrix<vtype, Nrepresentation>, Ns>, Ngp >;
template <typename vtype> using iImplHalfSpinor = iVector<iVector<iVector<vtype, Nrepresentation>, Nhs>, Ngp>;
template <typename vtype> using iImplDoubledGaugeField = iVector<iVector<iScalar<iMatrix<vtype, Nrepresentation> >, Nds>, Ngp>;
typedef iImplSpinor<Simd> SiteSpinor;
typedef iImplPropagator<Simd> SitePropagator;
typedef iImplHalfSpinor<Simd> SiteHalfSpinor;
typedef iImplDoubledGaugeField<Simd> SiteDoubledGaugeField;
typedef Lattice<SiteSpinor> FermionField;
typedef Lattice<SitePropagator> PropagatorField;
typedef Lattice<SiteDoubledGaugeField> DoubledGaugeField;
typedef WilsonCompressor<SiteHalfSpinor, SiteSpinor> Compressor;

View File

@ -26,7 +26,7 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
See the full license in the file "LICENSE" in the top level distribution directory
*************************************************************************************/
/* END LEGAL */
#include <Grid.h>
#include <Grid/Grid.h>
namespace Grid {
namespace QCD {

View File

@ -29,7 +29,7 @@ See the full license in the file "LICENSE" in the top level distribution
directory
*************************************************************************************/
/* END LEGAL */
#include <Grid.h>
#include <Grid/Grid.h>
namespace Grid {
namespace QCD {
@ -61,7 +61,9 @@ WilsonFermion<Impl>::WilsonFermion(GaugeField &_Umu, GridCartesian &Fgrid,
LebesgueEvenOdd(_cbgrid),
Umu(&Fgrid),
UmuEven(&Hgrid),
UmuOdd(&Hgrid) {
UmuOdd(&Hgrid),
_tmp(&Hgrid)
{
// Allocate the required comms buffer
ImportGauge(_Umu);
}
@ -147,11 +149,11 @@ void WilsonFermion<Impl>::MeooeDag(const FermionField &in, FermionField &out) {
typedef Lattice<iSinglet<vector_type> > LatComplex;
Gamma::GammaMatrix Gmu [] = {
Gamma::GammaX,
Gamma::GammaY,
Gamma::GammaZ,
Gamma::GammaT
Gamma::Algebra Gmu [] = {
Gamma::Algebra::GammaX,
Gamma::Algebra::GammaY,
Gamma::Algebra::GammaZ,
Gamma::Algebra::GammaT
};
std::vector<int> latt_size = _grid->_fdimensions;

View File

@ -58,6 +58,9 @@ class WilsonFermion : public WilsonKernels<Impl>, public WilsonFermionStatic {
GridBase *FermionGrid(void) { return _grid; }
GridBase *FermionRedBlackGrid(void) { return _cbgrid; }
FermionField _tmp;
FermionField &tmp(void) { return _tmp; }
//////////////////////////////////////////////////////////////////
// override multiply; cut number routines if pass dagger argument
// and also make interface more uniformly consistent

Some files were not shown because too many files have changed in this diff Show More