diff --git a/CMakeLists.txt b/CMakeLists.txt index 148b89dd01178eb88051a6feff89f9525434624a..a76751f64600ed3d5140ac69c80799745be011d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,7 +225,10 @@ set(cpp_for_lib ${PROJECT_SOURCE_DIR}/cpp/full_code/NSVEparticles.cpp ${PROJECT_SOURCE_DIR}/cpp/full_code/NSVEcomplex_particles.cpp ${PROJECT_SOURCE_DIR}/cpp/full_code/NSVEp_extra_sampling.cpp - ${PROJECT_SOURCE_DIR}/cpp/particles/particles_inner_computer.cpp) + ${PROJECT_SOURCE_DIR}/cpp/particles/particles_inner_computer.cpp + ${PROJECT_SOURCE_DIR}/cpp/full_code/ornstein_uhlenbeck_process.cpp + ${PROJECT_SOURCE_DIR}/cpp/full_code/ou_vorticity_equation.cpp) + set(hpp_for_lib ${PROJECT_SOURCE_DIR}/cpp/full_code/code_base.hpp ${PROJECT_SOURCE_DIR}/cpp/full_code/direct_numerical_simulation.hpp @@ -305,6 +308,8 @@ set(hpp_for_lib ${PROJECT_SOURCE_DIR}/cpp/omputils.hpp ${PROJECT_SOURCE_DIR}/cpp/shared_array.hpp ${PROJECT_SOURCE_DIR}/cpp/spline.hpp + ${PROJECT_SOURCE_DIR}/cpp/full_code/ornstein_uhlenbeck_process.hpp + ${PROJECT_SOURCE_DIR}/cpp/full_code/ou_vorticity_equation.hpp ) #file(GLOB_RECURSE hpp_for_lib ${PROJECT_SOURCE_DIR}/*.hpp) LIST(APPEND source_files ${hpp_for_lib} ${cpp_for_lib}) @@ -336,4 +341,3 @@ else() install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/pc_host_info.py ${PROJECT_BINARY_DIR}/python/TurTLE/host_info.py)") endif() install(CODE "execute_process(COMMAND python3 ${PROJECT_SOURCE_DIR}/setup.py install --force --prefix=${CMAKE_INSTALL_PREFIX} WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/python/)") - diff --git a/TurTLE/DNS.py b/TurTLE/DNS.py index 9b490c778b5cdf97d0ef0b7cf2f0244e9ee68d45..1d5bea0ca4cb3e01b03b8562bd006d3af2c2ced3 100644 --- a/TurTLE/DNS.py +++ b/TurTLE/DNS.py @@ -2,20 +2,20 @@ # # # Copyright 2015-2019 Max Planck Institute for Dynamics and Self-Organization # # # -# This file is part of TurTLE. # +# This file is part of TurTLE. # # # -# TurTLE is free software: you can redistribute it and/or modify # +# TurTLE 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 3 of the License, # # or (at your option) any later version. # # # -# TurTLE is distributed in the hope that it will be useful, # +# TurTLE 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 TurTLE. If not, see <http://www.gnu.org/licenses/> # +# along with TurTLE. If not, see <http://www.gnu.org/licenses/> # # # # Contact: Cristian.Lalescu@ds.mpg.de # # # @@ -657,7 +657,9 @@ class DNS(_code): parser_NSVEp_extra = subparsers.add_parser( 'NSVEp_extra_sampling', help = 'plain Navier-Stokes vorticity formulation, with basic fluid tracers, that sample velocity gradient, as well as pressure and its derivatives.') - + parser_NSVE_ou = subparsers.add_parser( + 'NSVE_ou_forcing', + help = 'plain Navier-Stokes vorticity formulation, with ornstein-uhlenbeck forcing') for parser in ['NSVEparticles_no_output', 'NSVEp2', 'NSVEp2p', 'NSVEp_extra', 'static_field']: eval('self.simulation_parser_arguments({0})'.format('parser_' + parser)) eval('self.job_parser_arguments({0})'.format('parser_' + parser)) @@ -1060,4 +1062,3 @@ class DNS(_code): no_submit = opt.no_submit, no_debug = opt.no_debug) return None - diff --git a/TurTLE/TEST.py b/TurTLE/TEST.py index dbf166d413dc2024e09e0e66c6e8b97d4c74df71..14f1e138ab3c2ce411d81990faa351557d820e94 100644 --- a/TurTLE/TEST.py +++ b/TurTLE/TEST.py @@ -275,12 +275,18 @@ class TEST(_code): parser_test_interpolation = subparsers.add_parser( 'test_interpolation', help = 'test velocity gradient interpolation') + + parser_ornstein_uhlenbeck_test = subparsers.add_parser( + 'ornstein_uhlenbeck_test', + help = 'test ornstein uhlenbeck process') + for parser in ['parser_filter_test', 'parser_write_filtered_test', 'parser_field_test', 'parser_symmetrize_test', 'parser_field_output_test', - 'parser_test_interpolation']: + 'parser_test_interpolation', + 'parser_ornstein_uhlenbeck_test']: eval('self.simulation_parser_arguments(' + parser + ')') eval('self.job_parser_arguments(' + parser + ')') eval('self.parameters_to_parser_arguments(' + parser + ')') @@ -368,6 +374,8 @@ class TEST(_code): ofile.require_group('tracers0') for kk in ['position', 'velocity', 'vorticity', 'velocity_gradient']: ofile['tracers0'].require_group(kk) + + self.run( nb_processes = opt.nb_processes, nb_threads_per_process = opt.nb_threads_per_process, @@ -376,4 +384,3 @@ class TEST(_code): minutes = opt.minutes % 60, no_submit = opt.no_submit) return None - diff --git a/cpp/full_code/NSVE.cpp b/cpp/full_code/NSVE.cpp index 21788cc9f305570dfdcd066421a83bbc065120ae..909994305db5c9233e028f22aa343766f1912281 100644 --- a/cpp/full_code/NSVE.cpp +++ b/cpp/full_code/NSVE.cpp @@ -62,11 +62,11 @@ int NSVE<rnumber>::initialize(void) } this->fs = new vorticity_equation<rnumber, FFTW>( simname.c_str(), - nx, ny, nz, - dkx, dky, dkz, + this->nx, this->ny, this->nz, + this->dkx, this->dky, this->dkz, fftw_planner_string_to_flag[this->fftw_plan_rigor]); this->tmp_vec_field = new field<rnumber, FFTW, THREE>( - nx, ny, nz, + this->nx, this->ny, this->nz, this->comm, fftw_planner_string_to_flag[this->fftw_plan_rigor]); diff --git a/cpp/full_code/ornstein_uhlenbeck_process.cpp b/cpp/full_code/ornstein_uhlenbeck_process.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b6af42d324a27cddedd56aefbf7c57632ce186c6 --- /dev/null +++ b/cpp/full_code/ornstein_uhlenbeck_process.cpp @@ -0,0 +1,280 @@ +#include "ornstein_uhlenbeck_process.hpp" +#include <cmath> +#include <cstring> +#include <cassert> +#include "scope_timer.hpp" +#include <algorithm> +#define NDEBUG + + +template <class rnumber,field_backend be> +ornstein_uhlenbeck_process<rnumber,be>::ornstein_uhlenbeck_process( + const char *NAME, + int nx, + int ny, + int nz, + double ou_kmin, + double ou_kmax, + double ou_energy_amplitude, + double DKX, + double DKY, + double DKZ, + unsigned FFTW_PLAN_RIGOR) +{ + TIMEZONE("ornstein_uhlenbeck_process::ornstein_uhlenbeck_process"); + strncpy(this->name, NAME, 256); + this->name[255] = '\0'; + this->iteration = 0; + this->ou_field = new field<rnumber,be,THREE>( + nx,ny,nz, MPI_COMM_WORLD, FFTW_PLAN_RIGOR); + *this->ou_field = 0.0; + this->ou_field->dft(); + + this->ou_field_vort = new field<rnumber,be,THREE>( + nx,ny,nz, MPI_COMM_WORLD, FFTW_PLAN_RIGOR); + *this->ou_field_vort = 0.0; + this->ou_field_vort->dft(); + + this->B = new field<rnumber,be,THREExTHREE>( + nx,ny,nz, MPI_COMM_WORLD, FFTW_PLAN_RIGOR); + + this->kk = new kspace<be,SMOOTH>( + this->ou_field->clayout, DKX, DKY, DKZ); + + this->ou_kmin_squ = pow(ou_kmin,2); + this->ou_kmax_squ = pow(ou_kmax,2); + this->ou_energy_amplitude = ou_energy_amplitude; + this->epsilon = pow((this->ou_energy_amplitude/this->kolmogorov_constant), 3./2.); + + assert(this->kk->kM2 >= this->ou_kmax_squ); + + gen.resize(omp_get_max_threads()); + + for(int thread=0;thread<omp_get_max_threads();thread++) + { + int current_seed = + this->ou_field->clayout->myrank*omp_get_max_threads() + + thread; + gen[thread].seed(current_seed); + } + + + this->initialize_B(); + +} + +template <class rnumber,field_backend be> +ornstein_uhlenbeck_process<rnumber,be>::~ornstein_uhlenbeck_process() +{ + TIMEZONE("ornstein_uhlenbeck_process::~ornstein_uhlenbeck_process"); + delete this->kk; + delete this->ou_field; + delete this->ou_field_vort; + delete this->B; +} + +template <class rnumber,field_backend be> +void ornstein_uhlenbeck_process<rnumber,be>::step( + double dt) +{ + // put in "CFL"-criterium TODO!!! + TIMEZONE("ornstein_uhlenbeck_process::step"); + this->kk->CLOOP_K2( + [&](ptrdiff_t cindex, + ptrdiff_t xindex, + ptrdiff_t yindex, + ptrdiff_t zindex, + double k2){ + if (k2 <= this->ou_kmax_squ && k2 >= this->ou_kmin_squ) + { + double g = this->gamma(sqrt(k2)); + int tr = omp_get_thread_num(); + double random[6] = + { + this->d(this->gen[tr]),this->d(this->gen[tr]),this->d(this->gen[tr]), + this->d(this->gen[tr]),this->d(this->gen[tr]),this->d(this->gen[tr]) + }; + for (int cc=0; cc<3; cc++) for (int i=0; i<2; i++) + this->ou_field->cval(cindex,cc,i) = + (1-dt*g) * this->ou_field->cval(cindex,cc,i) + + sqrt(dt) * ( + this->B->cval(cindex,0,cc,0) * random[0+3*i] + + this->B->cval(cindex,1,cc,0) * random[1+3*i] + + this->B->cval(cindex,2,cc,0) * random[2+3*i] ); + + } + }); + + this->ou_field->symmetrize(); + this->calc_ou_vorticity(); + +} + + +template <class rnumber, field_backend be> +void ornstein_uhlenbeck_process<rnumber,be>::initialize_B() +{ + TIMEZONE("ornstein_uhlenbeck_process::initialize_B"); + *this->B = 0.0; + this->kk->CLOOP( + [&](ptrdiff_t cindex, + ptrdiff_t xindex, + ptrdiff_t yindex, + ptrdiff_t zindex){ + double ksqu = pow(this->kk->kx[xindex],2)+ + pow(this->kk->ky[yindex],2)+ + pow(this->kk->kz[zindex],2); + if (ksqu <= this->ou_kmax_squ && ksqu >= this->ou_kmin_squ) + { + double kabs = sqrt(ksqu); + double sigma; + if (ksqu == 0 || ksqu == this->ou_kmax_squ) + { + ksqu = 1; kabs = 1; sigma = 0; + } + else + { + sigma = + sqrt(4*this->gamma(kabs)*this->energy(kabs) + /(4*M_PI*ksqu)); + } + + for(int i=0;i<3;i++) { + for(int j=0;j<3;j++) { + + if (i+j == 0) + this->B->cval(cindex,i,j,0) = + sigma/2. * (1-pow(this->kk->kx[xindex],2)/ksqu); + + if (i+j == 4) + this->B->cval(cindex,i,j,0) = + sigma/2. * (1-pow(this->kk->kz[zindex],2)/ksqu); + + if (i+j == 1) + this->B->cval(cindex,i,j,0) = + sigma/2. * (0-this->kk->kx[xindex]*this->kk->ky[yindex]/ksqu); + + if (i+j == 3) + this->B->cval(cindex,i,j,0) = + sigma/2. * (0-this->kk->kz[zindex]*this->kk->ky[yindex]/ksqu); + + if (i+j == 2) { + + if(i==j) + this->B->cval(cindex,i,j,0) = + sigma/2. * (1-pow(this->kk->ky[yindex],2)/ksqu); + + if(i!=j) + this->B->cval(cindex,i,j,0) = + sigma/2. * (0-this->kk->kx[xindex]*this->kk->kz[zindex]/ksqu); + } + } + } + } + + }); +} + + +template <class rnumber, field_backend be> +void ornstein_uhlenbeck_process<rnumber, be>::let_converge(void) +{ + //add some logic here TODO + for(int i=0; i<1000; i++) + { + this->step(2e-3); + } +} + +template <class rnumber, field_backend be> +void ornstein_uhlenbeck_process<rnumber, be>::strip_from_field( + field<rnumber, be, THREE> *src) +{ + assert(src->real_space_representation==false); + + this->kk->CLOOP_K2( + [&](ptrdiff_t cindex, + ptrdiff_t xindex, + ptrdiff_t yindex, + ptrdiff_t zindex, + double k2){ + + if (k2 <= this->ou_kmax_squ && k2 >= this->ou_kmin_squ){ + + for(int cc=0; cc < 3; cc++){ + for(int imag=0; imag < 2; imag++){ + src->cval(cindex,cc,imag) = 0; + } + } + } + + } + + ); + +} + +template <class rnumber, field_backend be> +void ornstein_uhlenbeck_process<rnumber,be>::add_to_field_replace( + field<rnumber, be, THREE> *src, std::string uv) +{ + assert(src->real_space_representation==false); + assert((uv == "vorticity") || (uv == "velocity")); + + field<rnumber, be, THREE> *field_to_replace; + + if (uv == "vorticity") field_to_replace = this->ou_field_vort; + else field_to_replace = this->ou_field; + + this->kk->CLOOP_K2( + [&](ptrdiff_t cindex, + ptrdiff_t xindex, + ptrdiff_t yindex, + ptrdiff_t zindex, + double k2){ + + if (k2 <= this->ou_kmax_squ && k2 >= this->ou_kmin_squ){ + + rnumber tmp; + + for(int cc=0; cc < 3; cc++){ + for(int imag=0; imag < 2; imag++){ + tmp = field_to_replace->cval(cindex,cc,imag); + src->cval(cindex,cc,imag) = tmp; + } + } + } + + } + + ); +} + + +template <class rnumber, field_backend be> +void ornstein_uhlenbeck_process<rnumber,be>::calc_ou_vorticity(void) +{ + this->kk->CLOOP_K2( + [&](ptrdiff_t cindex, + ptrdiff_t xindex, + ptrdiff_t yindex, + ptrdiff_t zindex, + double k2){ + if (k2 <= this->kk->kM2) + { + this->ou_field_vort->cval(cindex,0,0) = -(this->kk->ky[yindex]*this->ou_field->cval(cindex,2,1) - this->kk->kz[zindex]*this->ou_field->cval(cindex,1,1)); + this->ou_field_vort->cval(cindex,0,1) = (this->kk->ky[yindex]*this->ou_field->cval(cindex,2,0) - this->kk->kz[zindex]*this->ou_field->cval(cindex,1,0)); + this->ou_field_vort->cval(cindex,1,0) = -(this->kk->kz[zindex]*this->ou_field->cval(cindex,0,1) - this->kk->kx[xindex]*this->ou_field->cval(cindex,2,1)); + this->ou_field_vort->cval(cindex,1,1) = (this->kk->kz[zindex]*this->ou_field->cval(cindex,0,0) - this->kk->kx[xindex]*this->ou_field->cval(cindex,2,0)); + this->ou_field_vort->cval(cindex,2,0) = -(this->kk->kx[xindex]*this->ou_field->cval(cindex,1,1) - this->kk->ky[yindex]*this->ou_field->cval(cindex,0,1)); + this->ou_field_vort->cval(cindex,2,1) = (this->kk->kx[xindex]*this->ou_field->cval(cindex,1,0) - this->kk->ky[yindex]*this->ou_field->cval(cindex,0,0)); + } + else + std::fill_n((rnumber*)(this->ou_field_vort->get_cdata()+3*cindex), 6, 0.0); + } + ); + this->ou_field_vort->symmetrize(); +} + +template class ornstein_uhlenbeck_process<float,FFTW>; +template class ornstein_uhlenbeck_process<double,FFTW>; diff --git a/cpp/full_code/ornstein_uhlenbeck_process.hpp b/cpp/full_code/ornstein_uhlenbeck_process.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a1aeaa98dd948ca39b2c96177341890b345c9953 --- /dev/null +++ b/cpp/full_code/ornstein_uhlenbeck_process.hpp @@ -0,0 +1,76 @@ +#ifndef ORNSTEIN_UHLENBECK_PROCESS_HPP +#define ORNSTEIN_UHLENBECK_PROCESS_HPP + +#include <sys/stat.h> +#include <stdio.h> +#include <stdlib.h> +#include <iostream> +#include "field.hpp" +#include <random> + +extern int myrank, nprocs; + +template <typename rnumber, field_backend be> +class ornstein_uhlenbeck_process{ + public: + char name[256]; + + int iteration; + double ou_kmin_squ; + double ou_kmax_squ; + double ou_energy_amplitude; + double kolmogorov_constant = 2; + double epsilon; + + field<rnumber,be,THREE> *ou_field; + field<rnumber,be,THREE> *ou_field_vort; + field<rnumber,be,THREExTHREE> *B; + kspace<be,SMOOTH> *kk; + + std::vector<std::mt19937_64> gen; + std::normal_distribution<double> d{0,1}; + + ornstein_uhlenbeck_process( + const char *NAME, + int nx, + int ny, + int nz, + double ou_kmin, + double ou_kmax, + double ou_energy_amplitude, + double DKX = 1.0, + double DKY = 1.0, + double DKZ = 1.0, + unsigned FFTW_PLAN_RIGOR = FFTW_MEASURE); + ~ornstein_uhlenbeck_process(void); + + void step(double dt); + inline double energy(double kabs) + { + return this->ou_energy_amplitude * pow(kabs,-5./3); + } + + inline double gamma(double kabs) + { + return this->kolmogorov_constant*sqrt(this->kolmogorov_constant/ + this->ou_energy_amplitude); + } + + + void initialize_B(void); + + void let_converge(void); + + void add_to_field_replace( + field<rnumber,be,THREE> *src, std::string uv); + + void strip_from_field( + field<rnumber, be, THREE> *src); + + void calc_ou_vorticity(void); + + +}; + + +#endif diff --git a/cpp/full_code/ou_vorticity_equation.cpp b/cpp/full_code/ou_vorticity_equation.cpp new file mode 100644 index 0000000000000000000000000000000000000000..37d3570d6f0c19849f5b584d4eaac5c7ed60c43f --- /dev/null +++ b/cpp/full_code/ou_vorticity_equation.cpp @@ -0,0 +1,164 @@ +#include "ou_vorticity_equation.hpp" +#include <cmath> +#include <cstring> +#include <cassert> +#include "scope_timer.hpp" +#define NDEBUG + + +template <class rnumber, field_backend be> +ou_vorticity_equation<rnumber,be>::~ou_vorticity_equation() +{ + delete this->ou; +} + +template <class rnumber, + field_backend be> +void ou_vorticity_equation<rnumber, be>::step(double dt) +{ + DEBUG_MSG("vorticity_equation::step\n"); + TIMEZONE("vorticity_equation::step"); + this->ou->add_to_field_replace(this->cvorticity, "vorticity"); + *this->v[1] = 0.0; + this->omega_nonlin(0); + this->kk->CLOOP_K2( + [&](ptrdiff_t cindex, + ptrdiff_t xindex, + ptrdiff_t yindex, + ptrdiff_t zindex, + double k2){ + if (k2 <= this->kk->kM2) + { + double factor0; + factor0 = exp(-this->nu * k2 * dt); + for (int cc=0; cc<3; cc++) for (int i=0; i<2; i++) + this->v[1]->cval(cindex,cc,i) = ( + this->v[0]->cval(cindex,cc,i) + + dt*this->u->cval(cindex,cc,i))*factor0; + } + } + ); + + this->omega_nonlin(1); + this->kk->CLOOP_K2( + [&](ptrdiff_t cindex, + ptrdiff_t xindex, + ptrdiff_t yindex, + ptrdiff_t zindex, + double k2){ + if (k2 <= this->kk->kM2) + { + double factor0, factor1; + factor0 = exp(-this->nu * k2 * dt/2); + factor1 = exp( this->nu * k2 * dt/2); + for (int cc=0; cc<3; cc++) for (int i=0; i<2; i++) + this->v[2]->cval(cindex, cc, i) = ( + 3*this->v[0]->cval(cindex,cc,i)*factor0 + + ( this->v[1]->cval(cindex,cc,i) + + dt*this->u->cval(cindex,cc,i))*factor1)*0.25; + } + } + ); + + this->omega_nonlin(2); + // store old vorticity + *this->v[1] = *this->v[0]; + this->kk->CLOOP_K2( + [&](ptrdiff_t cindex, + ptrdiff_t xindex, + ptrdiff_t yindex, + ptrdiff_t zindex, + double k2){ + if (k2 <= this->kk->kM2) + { + double factor0; + factor0 = exp(-this->nu * k2 * dt * 0.5); + for (int cc=0; cc<3; cc++) for (int i=0; i<2; i++) + this->v[3]->cval(cindex,cc,i) = ( + this->v[0]->cval(cindex,cc,i)*factor0 + + 2*(this->v[2]->cval(cindex,cc,i) + + dt*this->u->cval(cindex,cc,i)))*factor0/3; + } + } + ); + + this->kk->template force_divfree<rnumber>(this->cvorticity->get_cdata()); + this->cvorticity->symmetrize(); + this->iteration++; +} + + +template <class rnumber, field_backend be> +void ou_vorticity_equation<rnumber, be>::omega_nonlin(int src) +{ + DEBUG_MSG("ou_vorticity_equation::omega_nonlin(%d)\n", src); + assert(src >= 0 && src < 3); + this->compute_velocity(this->v[src]); + + this->add_ou_forcing_velocity(); + // TIME STEP TODO + + /* get fields from Fourier space to real space */ + this->u->ift(); + this->rvorticity->real_space_representation = false; + *this->rvorticity = this->v[src]->get_cdata(); + this->rvorticity->ift(); + /* compute cross product $u \times \omega$, and normalize */ + this->u->RLOOP( + [&](ptrdiff_t rindex, + ptrdiff_t xindex, + ptrdiff_t yindex, + ptrdiff_t zindex){ + rnumber tmp[3]; + for (int cc=0; cc<3; cc++) + tmp[cc] = (this->u->rval(rindex,(cc+1)%3)*this->rvorticity->rval(rindex,(cc+2)%3) - + this->u->rval(rindex,(cc+2)%3)*this->rvorticity->rval(rindex,(cc+1)%3)); + for (int cc=0; cc<3; cc++) + this->u->rval(rindex,cc) = tmp[cc] / this->u->npoints; + } + ); + /* go back to Fourier space */ + //this->clean_up_real_space(this->ru, 3); + this->u->dft(); + this->kk->template dealias<rnumber, THREE>(this->u->get_cdata()); + /* $\imath k \times Fourier(u \times \omega)$ */ + this->kk->CLOOP( + [&](ptrdiff_t cindex, + ptrdiff_t xindex, + ptrdiff_t yindex, + ptrdiff_t zindex){ + rnumber tmp[3][2]; + { + tmp[0][0] = -(this->kk->ky[yindex]*this->u->cval(cindex,2,1) - this->kk->kz[zindex]*this->u->cval(cindex,1,1)); + tmp[1][0] = -(this->kk->kz[zindex]*this->u->cval(cindex,0,1) - this->kk->kx[xindex]*this->u->cval(cindex,2,1)); + tmp[2][0] = -(this->kk->kx[xindex]*this->u->cval(cindex,1,1) - this->kk->ky[yindex]*this->u->cval(cindex,0,1)); + tmp[0][1] = (this->kk->ky[yindex]*this->u->cval(cindex,2,0) - this->kk->kz[zindex]*this->u->cval(cindex,1,0)); + tmp[1][1] = (this->kk->kz[zindex]*this->u->cval(cindex,0,0) - this->kk->kx[xindex]*this->u->cval(cindex,2,0)); + tmp[2][1] = (this->kk->kx[xindex]*this->u->cval(cindex,1,0) - this->kk->ky[yindex]*this->u->cval(cindex,0,0)); + } + for (int cc=0; cc<3; cc++) for (int i=0; i<2; i++) + this->u->cval(cindex, cc, i) = tmp[cc][i]; + } + ); + this->kk->template force_divfree<rnumber>(this->u->get_cdata()); + this->u->symmetrize(); +} + +template <class rnumber, field_backend be> +void ou_vorticity_equation<rnumber, be>::add_ou_forcing_velocity() +{ + if (this->ou_forcing_type == "replace"){ + this->ou->add_to_field_replace(this->u,"velocity"); + } +} + +template <class rnumber, field_backend be> +void ou_vorticity_equation<rnumber, be>::add_ou_forcing_vorticity() +{ + if (this->ou_forcing_type == "replace"){ + this->ou->add_to_field_replace(this->cvorticity,"vorticity"); + } +} + +template class ou_vorticity_equation<float, FFTW>; +template class ou_vorticity_equation<double, FFTW>; diff --git a/cpp/full_code/ou_vorticity_equation.hpp b/cpp/full_code/ou_vorticity_equation.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e36292c2271616794815d43d084810b9daeb3fc9 --- /dev/null +++ b/cpp/full_code/ou_vorticity_equation.hpp @@ -0,0 +1,53 @@ +#ifndef OU_VORTICITY_EQUATION_HPP +#define OU_VORTICITY_EQUATION_HPP + +#include <cstdlib> +#include "vorticity_equation.hpp" +#include "ornstein_uhlenbeck_process.hpp" + + +// vorticity_equation<double, FFTW> *test; + +template <typename rnumber, field_backend be> +class ou_vorticity_equation : public vorticity_equation<rnumber, be> +{ + public: + + std::string ou_forcing_type; + + ornstein_uhlenbeck_process<rnumber,be> *ou; + ou_vorticity_equation( + const char *NAME, + int nx, + int ny, + int nz, + double ou_kmin, + double ou_kmax, + double ou_energy_amplitude, + double DKX = 1.0, + double DKY = 1.0, + double DKZ = 1.0, + unsigned FFTW_PLAN_RIGOR = FFTW_MEASURE): + vorticity_equation<rnumber,be>( + NAME, nx, ny, nz, + DKX,DKY,DKZ, FFTW_PLAN_RIGOR){ + this->ou = new ornstein_uhlenbeck_process<rnumber,be>( + NAME, + nx, ny, nz, + ou_kmin, ou_kmax, ou_energy_amplitude, + DKX, DKY, DKZ, FFTW_PLAN_RIGOR); + this->ou_forcing_type = "replace"; + } + + ~ou_vorticity_equation(); + + void omega_nonlin(int src); + void step(double dt); + + void add_ou_forcing_velocity(void); + void add_ou_forcing_vorticity(void); + +}; + + +#endif diff --git a/cpp/hdf5_tools.cpp b/cpp/hdf5_tools.cpp index 5a3aef39caa2824f4d08e579d35734a1438ba5ec..7e6869d84f4cb6283721f1c321d2a7aaf258401b 100644 --- a/cpp/hdf5_tools.cpp +++ b/cpp/hdf5_tools.cpp @@ -1,9 +1,11 @@ #include "hdf5_tools.hpp" +#include "scope_timer.hpp" #include <cfloat> #include <climits> int hdf5_tools::require_size_single_dataset(hid_t dset, int tsize) { + TIMEZONE("hdf5_tools::require_size_single_dataset"); int ndims; hsize_t space; space = H5Dget_space(dset); @@ -24,6 +26,7 @@ int hdf5_tools::require_size_single_dataset(hid_t dset, int tsize) int hdf5_tools::grow_single_dataset(hid_t dset, int tincrement) { + TIMEZONE("hdf5_tools::grow_single_dataset"); int ndims; hsize_t space; space = H5Dget_space(dset); @@ -48,6 +51,7 @@ herr_t hdf5_tools::require_size_dataset_visitor( const H5O_info_t *info, void *op_data) { + TIMEZONE("hdf5_tools::require_size_dataset_visitor"); if (info->type == H5O_TYPE_DATASET) { hsize_t dset = H5Dopen(o_id, name, H5P_DEFAULT); @@ -63,6 +67,7 @@ herr_t hdf5_tools::grow_dataset_visitor( const H5O_info_t *info, void *op_data) { + TIMEZONE("hdf5_tools::grow_dataset_visitor"); if (info->type == H5O_TYPE_DATASET) { hsize_t dset = H5Dopen(o_id, name, H5P_DEFAULT); @@ -78,6 +83,7 @@ int hdf5_tools::grow_file_datasets( const std::string group_name, int tincrement) { + TIMEZONE("hdf5_tools::grow_file_datasets"); int file_problems = 0; hid_t group; @@ -98,6 +104,7 @@ int hdf5_tools::require_size_file_datasets( const std::string group_name, int tsize) { + TIMEZONE("hdf5_tools::require_size_file_datasets"); int file_problems = 0; hid_t group; @@ -117,6 +124,7 @@ std::vector<number> hdf5_tools::read_vector( const hid_t group, const std::string dset_name) { + TIMEZONE("hdf5_tools::read_vector"); std::vector<number> result; hsize_t vector_length; // first, read size of array @@ -143,6 +151,7 @@ number hdf5_tools::read_value( const hid_t group, const std::string dset_name) { + TIMEZONE("hdf5_tools::read_value"); number result; hid_t dset; hid_t mem_dtype; @@ -177,6 +186,7 @@ std::vector<dtype> hdf5_tools::read_vector_with_single_rank( const hid_t file_id, const std::string dset_name) { + TIMEZONE("hdf5_tools::read_vector_with_single_rank"); std::vector<dtype> data; int vector_size; if (myrank == rank_to_use) @@ -208,6 +218,7 @@ std::string hdf5_tools::read_string( const hid_t group, const std::string dset_name) { + TIMEZONE("hdf5_tools::read_string"); if (H5Lexists(group, dset_name.c_str(), H5P_DEFAULT)) { hid_t dset = H5Dopen(group, dset_name.c_str(), H5P_DEFAULT); diff --git a/cpp/vorticity_equation.hpp b/cpp/vorticity_equation.hpp index cbff223e2d8119b37ef30b4e6b739aa64eff7039..09119cc48db3c37c4faf3c54162dbe5ebaea99e9 100644 --- a/cpp/vorticity_equation.hpp +++ b/cpp/vorticity_equation.hpp @@ -87,8 +87,8 @@ class vorticity_equation ~vorticity_equation(void); /* solver essential methods */ - void omega_nonlin(int src); - void step(double dt); + virtual void omega_nonlin(int src); + virtual void step(double dt); void impose_zero_modes(void); /** \brief Method that computes force and adds it to the right hand side of the NS equations. @@ -166,4 +166,3 @@ class vorticity_equation }; #endif//VORTICITY_EQUATION -