[Samples] Add C++ OpenMP example
This commit is contained in:
parent
3f6f580b25
commit
78d5809d6f
4 changed files with 119 additions and 8 deletions
|
|
@ -248,6 +248,7 @@ defaults.noDebugLinkFlags = ''
|
|||
defaults.warningFlags = '-Wall'
|
||||
defaults.buildPch = False
|
||||
env['pch_flags'] = []
|
||||
env['openmp_flag'] = '-fopenmp' # used to generate sample build scripts
|
||||
|
||||
if 'gcc' in env.subst('$CC'):
|
||||
defaults.optimizeCcFlags += ' -Wno-inline'
|
||||
|
|
@ -270,11 +271,13 @@ elif env['CC'] == 'cl': # Visual Studio
|
|||
defaults.warningFlags = '/W3'
|
||||
defaults.buildPch = True
|
||||
env['pch_flags'] = ['/FIpch/system.h']
|
||||
env['openmp_flag'] = '/openmp'
|
||||
|
||||
elif 'icc' in env.subst('$CC'):
|
||||
defaults.cxxFlags = '-std=c++0x'
|
||||
defaults.ccFlags = '-vec-report0 -diag-disable 1478'
|
||||
defaults.warningFlags = '-Wcheck'
|
||||
env['openmp_flag'] = '-openmp'
|
||||
|
||||
elif 'clang' in env.subst('$CC'):
|
||||
defaults.ccFlags = '-fcolor-diagnostics'
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ set(CMAKE_VERBOSE_MAKEFILE ON)
|
|||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
@cmake_extra@
|
||||
include_directories(@cmake_cantera_incdirs@)
|
||||
link_directories(@cmake_cantera_libdirs@)
|
||||
|
||||
|
|
|
|||
|
|
@ -4,16 +4,27 @@ Import('env', 'build', 'install', 'buildSample')
|
|||
|
||||
# (subdir, program name, [source extensions])
|
||||
samples = [
|
||||
('combustor', 'combustor', ['cpp']),
|
||||
('flamespeed', 'flamespeed', ['cpp']),
|
||||
('kinetics1', 'kinetics1', ['cpp']),
|
||||
('NASA_coeffs', 'NASA_coeffs', ['cpp']),
|
||||
('rankine', 'rankine', ['cpp']),
|
||||
('LiC6_electrode', 'LiC6_electrode', ['cpp'])
|
||||
('combustor', 'combustor', ['cpp'], False),
|
||||
('flamespeed', 'flamespeed', ['cpp'], False),
|
||||
('kinetics1', 'kinetics1', ['cpp'], False),
|
||||
('NASA_coeffs', 'NASA_coeffs', ['cpp'], False),
|
||||
('rankine', 'rankine', ['cpp'], False),
|
||||
('LiC6_electrode', 'LiC6_electrode', ['cpp'], False),
|
||||
('openmp_ignition', 'openmp_ignition', ['cpp'], True)
|
||||
]
|
||||
|
||||
for subdir, name, extensions in samples:
|
||||
for subdir, name, extensions, openmp in samples:
|
||||
localenv = env.Clone()
|
||||
if openmp:
|
||||
localenv.Append(CXXFLAGS=env['openmp_flag'], LINKFLAGS=env['openmp_flag'])
|
||||
localenv['cmake_extra'] = """
|
||||
find_package(OpenMP REQUIRED)
|
||||
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS})
|
||||
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS})
|
||||
"""
|
||||
else:
|
||||
localenv['cmake_extra'] = ''
|
||||
|
||||
buildSample(localenv.Program, pjoin(subdir, name),
|
||||
mglob(localenv, subdir, *extensions),
|
||||
CPPPATH=['#include'],
|
||||
|
|
|
|||
97
samples/cxx/openmp_ignition/openmp_ignition.cpp
Normal file
97
samples/cxx/openmp_ignition/openmp_ignition.cpp
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
// Ignition delay calculation with OpenMP. This example shows how to use OpenMP
|
||||
// to run multiple reactor network calculations in parallel by using separate
|
||||
// Cantera objects for each thread.
|
||||
|
||||
#include "cantera/zerodim.h"
|
||||
#include "cantera/IdealGasMix.h"
|
||||
|
||||
#include <omp.h>
|
||||
|
||||
using namespace Cantera;
|
||||
|
||||
void run()
|
||||
{
|
||||
// The number of threads can be set by setting the OMP_NUM_THREADS
|
||||
// environment variable before running the code.
|
||||
int nThreads = omp_get_max_threads();
|
||||
writelog("Running on {} threads\n\n", nThreads);
|
||||
|
||||
// Containers for Cantera objects to be used in different. Each thread needs
|
||||
// to have its own set of linked Cantera objects. Multiple threads accessing
|
||||
// the same objects at the same time will cause errors.
|
||||
std::vector<std::unique_ptr<IdealGasMix>> gases;
|
||||
std::vector<std::unique_ptr<IdealGasConstPressureReactor>> reactors;
|
||||
std::vector<std::unique_ptr<ReactorNet>> nets;
|
||||
|
||||
// Create and link the Cantera objects for each thread. This step should be
|
||||
// done in serial
|
||||
for (int i = 0; i < nThreads; i++) {
|
||||
gases.emplace_back(new IdealGasMix("gri30.xml", "gri30"));
|
||||
reactors.emplace_back(new IdealGasConstPressureReactor());
|
||||
nets.emplace_back(new ReactorNet());
|
||||
reactors.back()->insert(*gases.back());
|
||||
nets.back()->addReactor(*reactors.back());
|
||||
}
|
||||
|
||||
// Points at which to compute ignition delay time
|
||||
size_t nPoints = 50;
|
||||
vector_fp T0(nPoints);
|
||||
vector_fp ignition_time(nPoints);
|
||||
for (size_t i = 0; i < nPoints; i++) {
|
||||
T0[i] = 1000 + 500 * ((float) i) / ((float) nPoints);
|
||||
}
|
||||
|
||||
// Calculate the ignition delay at each initial temperature using multiple
|
||||
// threads.
|
||||
//
|
||||
// Note on 'schedule(static, 1)':
|
||||
// This option causes points [0, nThreads, 2*nThreads, ...] to be handled by
|
||||
// the same thread, rather than the default behavior of one thread handling
|
||||
// points [0 ... nPoints/nThreads]. This helps balance the workload for each
|
||||
// thread in cases where the workload is biased, e.g. calculations for low
|
||||
// T0 take longer than calculations for high T0.
|
||||
#pragma omp parallel for schedule(static, 1)
|
||||
for (size_t i = 0; i < nPoints; i++) {
|
||||
// Get the Cantera objects that were initialized for this thread
|
||||
size_t j = omp_get_thread_num();
|
||||
IdealGasMix& gas = *gases[j];
|
||||
Reactor& reactor = *reactors[j];
|
||||
ReactorNet& net = *nets[j];
|
||||
|
||||
// Set up the problem
|
||||
gas.setState_TPX(T0[i], OneAtm, "CH4:0.5, O2:1.0, N2:3.76");
|
||||
reactor.syncState();
|
||||
net.setInitialTime(0.0);
|
||||
|
||||
// Integrate until we satisfy a crude estimate of the ignition delay
|
||||
// time: time for T to increase by 500 K
|
||||
while (reactor.temperature() < T0[i] + 500) {
|
||||
net.step();
|
||||
}
|
||||
|
||||
// Save the ignition delay time for this temperature
|
||||
ignition_time[i] = net.time();
|
||||
}
|
||||
|
||||
// Print the computed ignition delays
|
||||
writelog(" T (K) t_ig (s)\n");
|
||||
writelog("-------- ----------\n");
|
||||
for (size_t i = 0; i < nPoints; i++) {
|
||||
writelog("{: 8.1f} {: 10.3e}\n", T0[i], ignition_time[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
run();
|
||||
appdelete();
|
||||
return 0;
|
||||
} catch (CanteraError& err) {
|
||||
// handle exceptions thrown by Cantera
|
||||
std::cout << err.what() << std::endl;
|
||||
std::cout << " terminating... " << std::endl;
|
||||
appdelete();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue