Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The ILC module extension #24

Open
wants to merge 10 commits into
base: patch_2020
Choose a base branch
from
19 changes: 19 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ OPTION(USE_MPI "use mpi, if found" ON) # use -DUSE_MPI=off to force disable use
OPTION(BUILD_SHARED_LIBS "Builds shared libraries if ON, static libraries if OFF" ON)
OPTION(SET_RPATH "set the rpath of the executable to the found libraries" ON)
OPTION(WITH_NSOLVER "compile support for the nsolver module" ON)
OPTION(WITH_ILC "compile programs for inclined layer convection" OFF)
OPTION(WITH_PYTHON "build a python wrapper, using boost-python" OFF)
OPTION(WITH_HDF5CXX "enable legacy file format using hdf5 cxx" OFF)
OPTION(WITH_GTEST "enable gtest unit testing" ON)
Expand Down Expand Up @@ -190,6 +191,15 @@ add_subdirectory(programs)
add_subdirectory(tools)
add_subdirectory(examples)

if (WITH_ILC)
if (NOT WITH_NSOLVER)
message(FATAL_ERROR "Compiling the ILC module requires -DWITH_NSOLVER=ON")
endif()
add_subdirectory(modules/ilc)
add_subdirectory(modules/ilc/programs)
add_subdirectory(modules/ilc/examples)
endif ()

# Check if we want to build the python wrapper and have boost-python
# If Python and boost.python are there, build python interface
if (WITH_PYTHON)
Expand All @@ -204,6 +214,9 @@ endif ()

enable_testing()
add_subdirectory(tests)
if (WITH_ILC)
add_subdirectory(modules/ilc/tests)
endif ()
if (WITH_PYTHON)
add_subdirectory(python-wrapper/tests)
endif()
Expand Down Expand Up @@ -292,6 +305,12 @@ else ()
message(" nsolver: disabled")
endif ()

if (WITH_ILC)
message(" Inclined layer convection: enabled")
else ()
message(" Inclined layer convection: disabled")
endif ()

if (WITH_PYTHON)
message(" Python wrapper: enabled")
else ()
Expand Down
32 changes: 32 additions & 0 deletions modules/ilc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# This file is a part of channelflow version 2.0 https://channelflow.ch.
# License is GNU GPL version 2 or later: ./LICENCE
#
# Include and configure the Inclined Layer Convection module of channelflow.
#
set(
ilc_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/ilcflags.cpp
${CMAKE_CURRENT_SOURCE_DIR}/obe.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ilc.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ilcdsi.cpp
)

set(
ilc_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/ilcflags.h
${CMAKE_CURRENT_SOURCE_DIR}/obe.h
${CMAKE_CURRENT_SOURCE_DIR}/ilc.h
${CMAKE_CURRENT_SOURCE_DIR}/ilcdsi.h
)

# Define the target with appropriate dependencies
install_channelflow_library(ilc)
target_link_fftw(ilc PRIVATE)
target_link_libraries(ilc PUBLIC chflow)
if (WITH_NSOLVER)
target_link_libraries(ilc PUBLIC nsolver)
endif ()

# Install header files
install(FILES ${ilc_HEADERS} DESTINATION include/modules/ilc)
6 changes: 6 additions & 0 deletions modules/ilc/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
set(ilc_EXAMPLES benchmark_ilc)

foreach (program ${ilc_EXAMPLES})
install_channelflow_application(${program} examples)
target_link_libraries(${program}_app PUBLIC ilc)
endforeach (program)
166 changes: 166 additions & 0 deletions modules/ilc/examples/benchmark_ilc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/**
* The classic benchmark program, like for pure shear flow
*
* This file is a part of channelflow version 2.0, https://channelflow.ch .
* License is GNU GPL version 2 or later: ./LICENSE
*
* Original author: Florian Reetz
*/

#include <iostream>
#include "channelflow/flowfield.h"
#include "modules/ilc/ilc.h"

#ifdef HAVE_MPI
#include <mpi.h>
#endif
#include "channelflow/cfmpi.h"

using namespace std;
using namespace chflow;

int main(int argc, char* argv[]) {
cfMPI_Init(&argc, &argv);
{
int taskid = 0;
#ifdef HAVE_MPI
MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
#endif
if (taskid == 0)
cout << "Starting channelflow benchmark" << endl;

string purpose(
"This program loads the field uinit from the harddisk and integrates\nit for 10 time units. The resulting "
"field is compared to the field\nufinal. Wall-clock time elapsed for each timeunit as well as an\naverage "
"are calculated.");
ArgList args(argc, argv, purpose);
int nproc0 = args.getint("-np0", "-nproc0", 0, "number of processes for transpose/parallel ffts");
int nproc1 = args.getint("-np1", "-nproc1", 0, "number of processes for slice fft");
bool fftwmeasure = args.getflag("-fftwmeasure", "--fftwmeasure", "use fftw_measure instead of fftw_patient");
bool fftwwisdom = args.getflag("-fftwwisdom", "--fftwwisdom", "try loading fftw wisdom");
bool saveresult = args.getflag("-s", "--saveresult", "save resulting field to uresult.nc");
string dir = args.getstr("-d", "--directory", ".", "directory where fields are found and stored");
args.check();

if (taskid == 0)
cout << "Creating CfMPI object..." << flush;
CfMPI* cfmpi = &CfMPI::getInstance(nproc0, nproc1);
if (taskid == 0)
cout << "done" << endl;

if (taskid == 0)
cout << "Loading FlowFields..." << endl;
FlowField u(dir + "/uinit", cfmpi);
FlowField temp(dir + "/tinit", cfmpi);
if (taskid == 0)
cout << "done" << endl;

if (u.taskid() == 0)
cout << "Calculating l2norm..." << flush;
Real ul2n = L2Norm(u);
Real tl2n = L2Norm(temp);
if (taskid == 0)
cout << "done" << endl;

if (u.taskid() == 0) {
cout << "================================================================\n";
cout << purpose << endl << endl;
cout << "Distribution of processes is " << u.nproc0() << "x" << u.nproc1() << endl;
}
if (fftwwisdom && u.taskid() == 0) {
cout << "Loading fftw wisdom" << endl;
fftw_loadwisdom();
}
if (u.taskid() == 0)
cout << "Optimizing FFTW..." << flush;
{
FlowField utmp(u);
if (fftwmeasure)
utmp.optimizeFFTW(FFTW_MEASURE);
else
utmp.optimizeFFTW(FFTW_PATIENT);
fftw_savewisdom();
}
if (u.taskid() == 0)
cout << "done" << endl;
ul2n = L2Norm(u);
tl2n = L2Norm(temp);
if (u.taskid() == 0)
cout << " L2Norm(u) == " << ul2n << endl;
if (u.taskid() == 0)
cout << " L2Norm(T) == " << tl2n << endl;

// Define integration parameters
const int n = 40; // take n steps between printouts
const Real dt = 1.0 / n; // integration timestep

// Define DNS parameters
ILCFlags flags;

// Run at default flags. If you change them, recreate the test files.
flags.dt = dt;
flags.verbosity = Silent;

if (u.taskid() == 0)
cout << "Building FlowField q..." << flush;
vector<FlowField> fields = {
u, temp, FlowField(u.Nx(), u.Ny(), u.Nz(), 1, u.Lx(), u.Lz(), u.a(), u.b(), u.cfmpi(), Spectral, Spectral)};
if (u.taskid() == 0)
cout << "done" << endl;
if (u.taskid() == 0)
cout << "Building dns..." << flush;
ILC ilc(fields, flags);
if (u.taskid() == 0)
cout << "done" << endl;

Real avtime = 0;
int i = 0;
Real T = 10;
for (Real t = 0; t <= T; t += 1) {
timeval start, end;
gettimeofday(&start, 0);
Real cfl = ilc.CFL(fields[0]);
if (fields[0].taskid() == 0)
cout << " t == " << t << endl;
if (fields[0].taskid() == 0)
cout << " CFL == " << cfl << endl;
Real ul2n = L2Norm(fields[0]);
Real tl2n = L2Norm(fields[1]);
if (fields[0].taskid() == 0)
cout << " L2Norm(u) == " << ul2n << endl;
if (fields[0].taskid() == 0)
cout << " L2Norm(T) == " << tl2n << endl;

// Take n steps of length dt
ilc.advance(fields, n);

gettimeofday(&end, 0);
Real sec = (Real)(end.tv_sec - start.tv_sec);
Real ms = (((Real)end.tv_usec) - ((Real)start.tv_usec));
Real timeused = sec + ms / 1000000.;
if (fields[0].taskid() == 0)
cout << "duration for this timeunit: " << timeused << endl;
if (t != 0) {
avtime += timeused;
i++;
}
if (fields[0].taskid() == 0)
cout << endl;
}

if (fields[0].taskid() == 0) {
cout << "Average time/timeunit: " << avtime / i << "s" << endl;
ofstream fout("benchmark_results", ios::app);
fout << "np0 x np1 == " << cfmpi->nproc0() << " x " << cfmpi->nproc1() << endl;
fout << "fftw_flag == " << (fftwmeasure ? "fftw_measure" : "fftw_patient") << endl;
fout << "Average time/timeunit: " << avtime / i << "s" << endl << endl;
fout.close();
}
// fftw_mpi_gather_wisdom(MPI_COMM_WORLD);
fftw_savewisdom();
if (saveresult)
fields[0].save(dir + "/uresult.nc");
}
cfMPI_Finalize();
return 0;
}
Loading