From 46c02945c361ae0bb9cea4fb869b313746bf9d49 Mon Sep 17 00:00:00 2001 From: "J.A. de Jong @ vulgaris" Date: Sat, 21 Feb 2015 19:46:54 +0100 Subject: [PATCH] Vectorized implementation. Does not work yet --- CMakeLists.txt | 3 + src/arma_numpy.cpp | 39 +++++----- src/arma_numpy.h | 14 +++- src/solutionatgp.cpp | 31 -------- src/solutionatgp.h | 38 ---------- src/solutioninstance.cpp | 32 ++------ src/solutioninstance.h | 59 +++++++++------ src/tube.cpp | 155 ++++++++++++++++++++------------------- src/tube.h | 61 ++++++++++----- timedomain.i | 40 ++++------ timedomain.ipynb | 143 +++++++++++++++++++++++++++++++----- 11 files changed, 336 insertions(+), 279 deletions(-) delete mode 100644 src/solutionatgp.cpp delete mode 100644 src/solutionatgp.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b2ee98..9743c45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,9 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) SET(CMAKE_SWIG_FLAGS "-Wall") +add_definitions(-DNDEBUG) #This is for BOOST functions, and to disable assertions! +# add_definitions(-DTRACER=0) +add_definitions(-DEIGEN_NO_DEBUG -DARMA_NO_DEBUG) add_definitions(-DTRACERNAME=timedomaineulertracer -DARMA_USE_BLAS -DARMA_USE_LAPACK) diff --git a/src/arma_numpy.cpp b/src/arma_numpy.cpp index 2761a69..9e4f635 100644 --- a/src/arma_numpy.cpp +++ b/src/arma_numpy.cpp @@ -1,3 +1,10 @@ +// arma_numpy.cpp +// +// last-edit-by: J.A. de Jong +// +// Description: +// +////////////////////////////////////////////////////////////////////// #define PY_ARRAY_UNIQUE_SYMBOL npy_array_api #define NO_IMPORT_ARRAY #include "arma_numpy.h" @@ -5,34 +12,30 @@ // Annes conversion functions. In a later stage they have to be // generalized for arrays of arbitrary dimensions +PyObject *npy_from_vd(const vd &in) { + long int size = in.size(); + npy_intp dims[1] = {size}; - -PyObject* npy_from_vd(const vd& in){ - long int size=in.size(); - npy_intp dims[1]={size}; // This code should be improved massively? - if(size==0){ + if (size == 0) { std::cout << "Size is zero!\n"; return NULL; } - cout << "SFSF\n"; - PyArrayObject* array = (PyArrayObject*) \ - PyArray_SimpleNew(1, dims, NPY_DOUBLE); - cout << "SFSF\n"; + PyArrayObject *array = + (PyArrayObject *)PyArray_SimpleNew(1, dims, NPY_DOUBLE); if (array == NULL) { return NULL; } - double *pydat= (double*) PyArray_DATA(array); - cout << "SFSF\n"; - mempcpy(pydat,in.memptr(),size*sizeof(double)); + double *pydat = (double *)PyArray_DATA(array); + mempcpy(pydat, in.memptr(), size * sizeof(double)); + return PyArray_Return(array); } -vd vd_from_npy(const PyArrayObject* const in){ +vd vd_from_npy(const PyArrayObject *const in) { - double* pydata = (double*) PyArray_DATA(in); - vd result; - // long int dims= - // PyArra - // vd res() + npy_intp size=PyArray_DIMS(in)[0]; // Extract first + double *pydata = (double *)PyArray_DATA(in); + vd result(size); + memcpy(result.memptr(),pydata,size*sizeof(double)); return result; } diff --git a/src/arma_numpy.h b/src/arma_numpy.h index 53b586c..7728f36 100644 --- a/src/arma_numpy.h +++ b/src/arma_numpy.h @@ -1,13 +1,25 @@ +// arma_numpy.h +// +// Author: J.A. de Jong +// +// Description: Header file for two function converting between Numpy +// arrays and armadillo matrices +////////////////////////////////////////////////////////////////////// #pragma once #ifndef ARMA_NUMPY_H -#define ARMA_NUMPY_H +#define ARMA_NUMPY_H 1 + #include #include #include "vtypes.h" + SPOILNAMESPACE vd vd_from_npy(PyArrayObject const * const); PyObject* npy_from_vd(const vd& armavec); + #endif // ARMA_NUMPY_H +////////////////////////////////////////////////////////////////////// + diff --git a/src/solutionatgp.cpp b/src/solutionatgp.cpp deleted file mode 100644 index f2d7f6d..0000000 --- a/src/solutionatgp.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "solutionatgp.h" -#include "globalconf.h" - - -TRACETHIS - -namespace td{ - extern tasystem::Globalconf gc; - - SolutionAtGp::SolutionAtGp() { - rho_=gc.rho0(); - } - d SolutionAtGp::u() const {return m()/rho();} - d SolutionAtGp::ekin() const {return 0.5*rho()*pow(u(),2);} - d SolutionAtGp::estat() const {return rhoE()-ekin();} - d SolutionAtGp::p() const {return estat()*(gc.gas.gamma(gc.T0)-1);} - - d SolutionAtGp::Cflux() const {return m();} - d SolutionAtGp::Mflux() const {return pow(m(),2)/rho()+p();} - d SolutionAtGp::Eflux() const {return (rhoE()+gc.p0/(gc.gas.gamma(gc.T0)-1)+p()+gc.p0)*u();} - -} // namespace td - - - - - - - - - diff --git a/src/solutionatgp.h b/src/solutionatgp.h deleted file mode 100644 index f62a11f..0000000 --- a/src/solutionatgp.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -namespace td{ - - typedef double d; - typedef unsigned us; - - class SolutionAtGp { - d rho_,m_=0,rhoE_=0; - public: - // Dependent variables - const d& rho() const {return rho_;} - const d& m() const {return m_;} // which is rho*u - const d& rhoE() const {return rhoE_;} // which is rho*E - // Derived from dependent - d u() const; - d ekin() const; - d estat() const; - d p() const; - - d Cflux() const; - d Mflux() const; - d Eflux() const; - SolutionAtGp(); - ~SolutionAtGp(){} - void setData(d rho,d m=0,d rhoE=0){ - rho_=rho; - m_=m; - rhoE_=rhoE; - } - }; -} // namespace td - - - - - - diff --git a/src/solutioninstance.cpp b/src/solutioninstance.cpp index 87c7490..aa4b74e 100644 --- a/src/solutioninstance.cpp +++ b/src/solutioninstance.cpp @@ -2,38 +2,18 @@ namespace td{ - SolutionInstance::SolutionInstance(int gp) + SolutionInstance::SolutionInstance(int gp,d rho) { TRACE(12,"SolutionInstance::SolutionInstance()"); - gps.resize(gp); + rho_=vd(gp,fillwith::zeros); + m_=vd(gp,fillwith::zeros); + rhoE_=vd(gp,fillwith::zeros); + } void SolutionInstance::setrho(d rho) { TRACE(15,"SolutionInstance::setrho()"); - - for(auto gp=gps.begin();gp!=gps.end();gp++){ - gp->setData(rho); - } + rho_=ones(rho_.size())*rho; } // setrho() - vd SolutionInstance::getrho() const{ - return gpsol_to_python(gps,&SolutionAtGp::rho); - } - vd SolutionInstance::getp() const{ - return gpsol_to_python(gps,&SolutionAtGp::p); - } - int SolutionInstance::save(std::ofstream& str,data d){ - TRACE(15,"SolutionInstance::save()"); - if(d==data::p) - for(us j=0;j - vd gpsol_to_python(const vector& gps,funptr fun){ - int size=gps.size(); - vd result(size); - for(int i=0;i gps; + + vd rho_,m_,rhoE_; d time=0; public: - SolutionInstance(int gp); + SolutionInstance(int gp,d rho=1.2); ~SolutionInstance(){} d getTime() const {return time;} void setTime(d t) {time=t;} - void setData(us i,SolutionAtGp& sol){ gps.at(i)=sol;} - SolutionAtGp& get(us i){ return gps.at(i); } - vd getp() const; - vd getrho() const; + vd& rho_ref(){ return rho_;} + vd& m_ref() {return m_;} + vd& rhoE_ref() {return rhoE_;} + const vd& rho() const {return rho_;} + const vd& m() const {return m_;} + const vd& rhoE() const {return rhoE_;} + vd p() const {return estat()*(gc.gas.gamma(gc.T0)-1);} + vd u() const {return m()/rho();} + vd ekin() const { return 0.5*rho()%pow(u(),2);} + vd estat() const {return rhoE()-ekin();} + vd Cflux() const {return m();} + vd Mflux() const {return pow(m(),2)/rho()+p();} + vd Eflux() const {return (rhoE()+gc.p0/(gc.gas.gamma(gc.T0)-1)+p()+gc.p0)%u();} + void setrho(d rho); - int save(std::ofstream&,data d); + }; } // namespace td + + +#endif // SOLUTIONINSTANCE_H +////////////////////////////////////////////////////////////////////// + diff --git a/src/tube.cpp b/src/tube.cpp index 7f666cb..8d02bed 100644 --- a/src/tube.cpp +++ b/src/tube.cpp @@ -1,91 +1,92 @@ #include "tube.h" -namespace td{ - tasystem::Globalconf gc; +TRACETHIS - d Tube::pleft(d t){ - d pleft=std::sin(gc.getomg()*t); - cout << "t:"<< t<sol=sol;} - void DoIntegration(d dt,int n=1); - d getTime(){return t;} - }; + virtual void Integrate(d dt) = 0; + + public: + Tube(double L, int gp) throw(int); + virtual ~Tube() {} + SolutionInstance &getSol() { return sol; } + void setSol(const SolutionInstance &sol) { this->sol = sol; } + void DoIntegration(d dt, int n = 1); + d getTime() { return t; } + }; + class TubeLF : public Tube { // Using Lax-Friedrichs method + protected: + virtual void Integrate(d dt); + + public: + using Tube::Tube; + + }; +} // namespace td + + + +#endif // TUBE_H +////////////////////////////////////////////////////////////////////// + + -} // namespace td -#endif /* _TUBE_H_ */ diff --git a/timedomain.i b/timedomain.i index f7ff060..d5d732d 100644 --- a/timedomain.i +++ b/timedomain.i @@ -35,13 +35,12 @@ class vd{ return NULL; int ndims=PyArray_DIM(arr,0); if(ndims!=1){ - PyErr_SetString(PyExc_TypeError,"Number of dimensions not equal to 1"); + // PyErr_SetString(PyExc_TypeError,"Number of dimensions not equal to 1"); return NULL; } $1= vd_from_npy(arr); } %typemap(out) vd { - cout << "Hoi\n"; $result=npy_from_vd($1); } typedef double d; @@ -95,46 +94,33 @@ namespace tasystem{ namespace td{ - class SolutionAtGp { - public: - const d& rho() const; - const d& m() const; - const d& rhoE() const; - d u() const; - d ekin() const; - d estat() const; - d p() const; - - d Cflux() const; - d Mflux() const; - d Eflux() const; - SolutionAtGp(); - ~SolutionAtGp(){} - void setData(d rho,d m=0,d rhoE=0); - }; class SolutionInstance{ public: - SolutionInstance(int gp); + SolutionInstance(int gp,d rho=1.2); ~SolutionInstance(){} - d getTime() const; - vd getrho() const; - vd getp() const; + vd rho() const; + vd p() const; + vd u() const; void setTime(d t); - void setData(us i,SolutionAtGp& sol); - SolutionAtGp& get(us i); void setrho(d rho); }; tasystem::Globalconf gc; class Tube{ + virtual void Integrate(d dt)=0; public: - Tube(double L,int gp); - ~Tube(){} + Tube(double L,int gp) throw(int); + virtual ~Tube(); SolutionInstance& getSol(); void setSol(const SolutionInstance& sol); void DoIntegration(d dt,int n=1); d getTime(); }; + class TubeLF:public Tube{ + virtual void Integrate(d dt); + public: + TubeLF(d L,int gp); + }; } diff --git a/timedomain.ipynb b/timedomain.ipynb index b2649f8..2b3144e 100644 --- a/timedomain.ipynb +++ b/timedomain.ipynb @@ -1,7 +1,7 @@ { "metadata": { "name": "", - "signature": "sha256:c219b2e07da88eca6f031393997d37a4b29390fb7116605d50ca9f4c6d0512b5" + "signature": "sha256:f48effc45d7e0ce53ecece3d2b83f5c45c2f29c363f0233fd7f2579385deda58" }, "nbformat": 3, "nbformat_minor": 0, @@ -17,7 +17,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": 1 }, { "cell_type": "code", @@ -28,64 +29,170 @@ "T=1/f\n", "loglevel=20\n", "L=1.0\n", - "gp=300\n", + "gp=400\n", "gc=cvar.gc #Reference!\n", "dx=L/(gp-1); # One left and right gp, so\n", - "CFL=0.9;\n", + "CFL=0.01;\n", "gc.setfreq(f)\n", - "tube=Tube(L,gp)\n", + "tube=TubeLF(L,gp)\n", "dt=min(CFL*dx/gc.c0(),T/50)" ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": 2 }, { "cell_type": "code", "collapsed": false, "input": [ - "sol=tube.getSol()" + "dt" ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 3, + "text": [ + "7.303933869608436e-08" + ] + } + ], + "prompt_number": 3 }, { "cell_type": "code", "collapsed": false, "input": [ - "#sol.getrho()" + "gc.c0()" ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 4, + "text": [ + "343.1391506142924" + ] + } + ], + "prompt_number": 4 }, { "cell_type": "code", "collapsed": false, "input": [ - "dt*gc.getfreq()" + "nr_p_period=1\n", + "intsteps=int(floor(1./(gc.getfreq()*dt)/nr_p_period))" ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": 5 }, { "cell_type": "code", "collapsed": false, "input": [ - "tube.DoIntegration(dt,10)\n", + "intsteps=100" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 6 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "print(\"DoIntegration relative time step of one period: %0.2e\" %(dt*gc.getfreq()))" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "DoIntegration relative time step of one period: 6.27e-06\n" + ] + } + ], + "prompt_number": 7 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "tube.DoIntegration(dt,intsteps)\n", "sol=tube.getSol()\n", - "rho=tube.getSol().getrho()\n", - "p=tube.getSol().getp()\n", - "figure(figsize=(12,4))\n", - "subplot(121)\n", + "u=sol.u()\n", + "p=sol.p()\n", + "rho=sol.rho()\n", + "figure(figsize=(9,6))\n", + "subplot(221)\n", "plot(p)\n", - "subplot(122)\n", + "subplot(222)\n", + "plot(u)\n", + "subplot(223)\n", "plot(rho)" ], "language": "python", "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 10, + "text": [ + "[]" + ] + }, + { + "metadata": {}, + "output_type": "display_data", + "png": "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\n", + "text": [ + "" + ] + } + ], + "prompt_number": 10 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [], + "language": "python", + "metadata": {}, + "outputs": [] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [], + "language": "python", + "metadata": {}, + "outputs": [] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [], + "language": "python", + "metadata": {}, + "outputs": [] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [], + "language": "python", + "metadata": {}, "outputs": [] } ],