/*
This file is part of the Snoopy code.
Snoopy code 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.
Snoopy code 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 Snoopy code. If not, see .
*/
#include
#include
#include "common.h"
#ifdef FORCING
/*****************************************************
** Here are several forcing possibilities which can **
** be used. Please remove comments to use a specific**
** forcing **
******************************************************/
/*****************************************************
** Random noise forcing ******************************
******************************************************/
void forcing(struct Field fldi,
double dt) {
// Force random velocity field
const double kf = 3.0 * M_PI * 2.0;
const double deltakf = kf * 0.2;
const double amplitude_forcing = 0.1;
// Force all the vector
int i,j,k;
int num_force=0;
int total_num_force;
double fact;
double q0;
q0=pow(dt,0.5);
for( i = 0; i < NX_COMPLEX/NPROC; i++) {
for( j = 0; j < NY_COMPLEX; j++) {
for( k = 0; k < NZ_COMPLEX; k++) {
if( (k2t[ IDX3D ]>(kf-deltakf)*(kf-deltakf)) && (k2t[ IDX3D ]<(kf+deltakf)*(kf+deltakf))) {
w4[ IDX3D ] = amplitude_forcing * mask[IDX3D] * randm() * cexp( I * 2.0*M_PI*randm() ) * NTOTAL*q0;
w5[ IDX3D ] = amplitude_forcing * mask[IDX3D] * randm() * cexp( I * 2.0*M_PI*randm() ) * NTOTAL*q0;
w6[ IDX3D ] = amplitude_forcing * mask[IDX3D] * randm() * cexp( I * 2.0*M_PI*randm() ) * NTOTAL*q0;
if(mask[IDX3D] > 0) num_force++;
}
else {
w4[ IDX3D ] = 0.0;
w5[ IDX3D ] = 0.0;
w6[ IDX3D ] = 0.0;
}
}
}
}
symmetrize_complex(w4);
if(rank==0) w4[0]=0.0;
symmetrize_complex(w5);
if(rank==0) w5[0]=0.0;
symmetrize_complex(w6);
if(rank==0) w6[0]=0.0;
// Get the total number of forced scales.
#ifdef MPI_SUPPORT
MPI_Allreduce( &num_force, &total_num_force, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
#else
total_num_force=num_force;
#endif
fact=pow(total_num_force,0.5);
for( i = 0; i < NX_COMPLEX/NPROC; i++) {
for( j = 0; j < NY_COMPLEX; j++) {
for( k = 0; k < NZ_COMPLEX; k++) {
fldi.vx[ IDX3D ] += w4[ IDX3D ] / fact;
fldi.vy[ IDX3D ] += w5[ IDX3D ] / fact;
fldi.vz[ IDX3D ] += w6[ IDX3D ] / fact;
}
}
}
projector(fldi.vx,fldi.vy,fldi.vz);
return;
}
/*****************************************************
** ABC FLOW forcing ************
** (Thanks to E. Rempel) ************
******************************************************/
/*
void forcing(struct Field fldi,
double dt) {
const double A=NTOTAL*1., B=NTOTAL*1., C=NTOTAL*1.;
const double kf=1.0;
int i, j, k;
int divisor,quociente,resto;
// ABC forcing
// Na direcao z nao precisa setar valores negativos de k, pois espelhamento e' feito automaticamente
if ((rank==0)){
i=0;
j=0;
k=kf;
fldi.vx[IDX3D] += -0.5*A*I * dt;
fldi.vy[IDX3D] += 0.5*A * dt;
i=0;
j=kf;
k=0;
fldi.vx[IDX3D] += 0.5*C * dt;
fldi.vz[IDX3D] += -0.5*C*I * dt;
j=NY_COMPLEX - kf;
fldi.vx[IDX3D] += 0.5*C * dt;
fldi.vz[IDX3D] += 0.5*C*I * dt;
}
divisor=NX_COMPLEX/NPROC;
quociente=(int)kf/divisor;
resto=fmod(kf,divisor);
// Somente kx eh paralelizado:
if (rank==quociente){
i=resto;
j=0;
k=0;
fldi.vy[IDX3D] += -0.5*B*I * dt;
fldi.vz[IDX3D] += 0.5*B * dt;
}
if (rank==(NPROC-1-quociente)){
i = NX_COMPLEX/NPROC-resto;
j=0;
k=0;
fldi.vy[IDX3D] += 0.5*B*I * dt;
fldi.vz[IDX3D] += 0.5*B * dt;
}
projector(fldi.vx,fldi.vy,fldi.vz);
return;
}
*/
#endif