00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "Sacado_Random.hpp"
00033 #include "Sacado.hpp"
00034
00035 #include "Fad/fad.h"
00036 #include "TinyFadET/tfad.h"
00037
00038 #include "Teuchos_Time.hpp"
00039 #include "Teuchos_CommandLineProcessor.hpp"
00040
00041
00042
00043
00044 template <>
00045 Sacado::Fad::MemPool* Sacado::Fad::MemPoolStorage<double>::defaultPool_ = NULL;
00046
00047 void FAD::error(const char *msg) {
00048 std::cout << msg << std::endl;
00049 }
00050
00051 namespace {
00052 double xi[3], xj[3], pa[4], f[3], delr[3];
00053 }
00054
00055 template <typename T>
00056 inline T
00057 vec3_distsq(const T xi[], const double xj[]) {
00058 T delr0 = xi[0]-xj[0];
00059 T delr1 = xi[1]-xj[1];
00060 T delr2 = xi[2]-xj[2];
00061 return delr0*delr0 + delr1*delr1 + delr2*delr2;
00062 }
00063
00064 template <typename T>
00065 inline T
00066 vec3_distsq(const T xi[], const double xj[], T delr[]) {
00067 delr[0] = xi[0]-xj[0];
00068 delr[1] = xi[1]-xj[1];
00069 delr[2] = xi[2]-xj[2];
00070 return delr[0]*delr[0] + delr[1]*delr[1] + delr[2]*delr[2];
00071 }
00072
00073 template <typename T>
00074 inline void
00075 lj(const T xi[], const double xj[], T& energy) {
00076 T delr2 = vec3_distsq(xi,xj);
00077 T delr_2 = 1.0/delr2;
00078 T delr_6 = delr_2*delr_2*delr_2;
00079 energy = (pa[1]*delr_6 - pa[2])*delr_6 - pa[3];
00080 }
00081
00082 inline void
00083 lj_and_grad(const double xi[], const double xj[], double& energy,
00084 double f[]) {
00085 double delr2 = vec3_distsq(xi,xj,delr);
00086 double delr_2 = 1.0/delr2;
00087 double delr_6 = delr_2*delr_2*delr_2;
00088 energy = (pa[1]*delr_6 - pa[2])*delr_6 - pa[3];
00089 double tmp = (-12.0*pa[1]*delr_6 - 6.0*pa[2])*delr_6*delr_2;
00090 f[0] = delr[0]*tmp;
00091 f[1] = delr[1]*tmp;
00092 f[2] = delr[2]*tmp;
00093 }
00094
00095 template <typename FadType>
00096 double
00097 do_time(int nloop)
00098 {
00099 Teuchos::Time timer("lj", false);
00100 FadType xi_fad[3], energy;
00101
00102 for (int i=0; i<3; i++) {
00103 xi_fad[i] = FadType(3, i, xi[i]);
00104 }
00105
00106 timer.start(true);
00107 for (int j=0; j<nloop; j++) {
00108
00109 lj(xi_fad, xj, energy);
00110
00111 for (int i=0; i<3; i++)
00112 f[i] += -energy.fastAccessDx(i);
00113 }
00114 timer.stop();
00115
00116 return timer.totalElapsedTime() / nloop;
00117 }
00118
00119 double
00120 do_time_analytic(int nloop)
00121 {
00122 Teuchos::Time timer("lj", false);
00123 double energy, ff[3];
00124
00125 timer.start(true);
00126 for (int j=0; j<nloop; j++) {
00127
00128 lj_and_grad(xi, xj, energy, ff);
00129
00130 for (int i=0; i<3; i++)
00131 f[i] += -ff[i];
00132
00133 }
00134 timer.stop();
00135
00136 return timer.totalElapsedTime() / nloop;
00137 }
00138
00139 int main(int argc, char* argv[]) {
00140 int ierr = 0;
00141
00142 try {
00143 double t, ta;
00144 int p = 2;
00145 int w = p+7;
00146
00147
00148 Teuchos::CommandLineProcessor clp;
00149 clp.setDocString("This program tests the speed of various forward mode AD implementations for a single multiplication operation");
00150 int nloop = 1000000;
00151 clp.setOption("nloop", &nloop, "Number of loops");
00152
00153
00154 Teuchos::CommandLineProcessor::EParseCommandLineReturn
00155 parseReturn= clp.parse(argc, argv);
00156 if(parseReturn != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL)
00157 return 1;
00158
00159
00160 Sacado::Fad::MemPoolManager<double> poolManager(3);
00161 Sacado::Fad::MemPool* pool = poolManager.getMemoryPool(3);
00162 Sacado::Fad::DMFad<double>::setDefaultPool(pool);
00163
00164 std::cout.setf(std::ios::scientific);
00165 std::cout.precision(p);
00166 std::cout << "Times (sec) nloop = " << nloop << ": " << std::endl;
00167
00168 Sacado::Random urand(0.0, 1.0);
00169 for (int i=0; i<3; i++) {
00170 xi[i] = urand.number();
00171 xj[i] = urand.number();
00172 pa[i] = urand.number();
00173 }
00174 pa[3] = urand.number();
00175
00176 ta = do_time_analytic(nloop);
00177 std::cout << "Analytic: " << std::setw(w) << ta << std::endl;
00178
00179 t = do_time< FAD::TFad<3,double> >(nloop);
00180 std::cout << "TFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00181
00182 t = do_time< FAD::Fad<double> >(nloop);
00183 std::cout << "Fad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00184
00185 t = do_time< Sacado::Fad::SFad<double,3> >(nloop);
00186 std::cout << "SFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00187
00188 t = do_time< Sacado::Fad::SLFad<double,3> >(nloop);
00189 std::cout << "SLFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00190
00191 t = do_time< Sacado::Fad::DFad<double> >(nloop);
00192 std::cout << "DFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00193
00194 t = do_time< Sacado::Fad::DMFad<double> >(nloop);
00195 std::cout << "DMFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00196
00197 t = do_time< Sacado::ELRFad::SFad<double,3> >(nloop);
00198 std::cout << "ELRSFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00199
00200 t = do_time< Sacado::ELRFad::SLFad<double,3> >(nloop);
00201 std::cout << "ELRSLFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00202
00203 t = do_time< Sacado::ELRFad::DFad<double> >(nloop);
00204 std::cout << "ELRDFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00205
00206 t = do_time< Sacado::CacheFad::DFad<double> >(nloop);
00207 std::cout << "CacheFad: " << std::setw(w) << t << "\t" << std::setw(w) << t/ta << std::endl;
00208
00209 }
00210 catch (std::exception& e) {
00211 cout << e.what() << endl;
00212 ierr = 1;
00213 }
00214 catch (const char *s) {
00215 cout << s << endl;
00216 ierr = 1;
00217 }
00218 catch (...) {
00219 cout << "Caught unknown exception!" << endl;
00220 ierr = 1;
00221 }
00222
00223 return ierr;
00224 }