sheet 5 not tested
This commit is contained in:
parent
9c16d18f8f
commit
64c7aed176
169 changed files with 225337 additions and 0 deletions
BIN
sheet1/F/main.GCC_
Executable file
BIN
sheet1/F/main.GCC_
Executable file
Binary file not shown.
BIN
sheet1/F/main.o
Normal file
BIN
sheet1/F/main.o
Normal file
Binary file not shown.
59
sheet5/1/.vscode/settings.json
vendored
Normal file
59
sheet5/1/.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"iostream": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"bit": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"charconv": "cpp",
|
||||||
|
"chrono": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"compare": "cpp",
|
||||||
|
"concepts": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"list": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"format": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"numbers": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"span": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"typeinfo": "cpp",
|
||||||
|
"variant": "cpp"
|
||||||
|
}
|
||||||
|
}
|
||||||
2877
sheet5/1/Doxyfile
Normal file
2877
sheet5/1/Doxyfile
Normal file
File diff suppressed because it is too large
Load diff
0
sheet5/1/Doxyfile:Zone.Identifier
Normal file
0
sheet5/1/Doxyfile:Zone.Identifier
Normal file
30
sheet5/1/Makefile
Normal file
30
sheet5/1/Makefile
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#
|
||||||
|
# use GNU-Compiler tools
|
||||||
|
COMPILER=GCC_
|
||||||
|
# alternatively from the shell
|
||||||
|
# export COMPILER=GCC_
|
||||||
|
# or, alternatively from the shell
|
||||||
|
# make COMPILER=GCC_
|
||||||
|
|
||||||
|
# use Intel compilers
|
||||||
|
#COMPILER=ICC_
|
||||||
|
|
||||||
|
# use PGI compilers
|
||||||
|
# COMPILER=PGI_
|
||||||
|
|
||||||
|
|
||||||
|
SOURCES = main.cpp mylib.cpp
|
||||||
|
OBJECTS = $(SOURCES:.cpp=.o)
|
||||||
|
|
||||||
|
PROGRAM = main.${COMPILER}
|
||||||
|
|
||||||
|
# uncomment the next to lines for debugging and detailed performance analysis
|
||||||
|
CXXFLAGS += -g
|
||||||
|
LINKFLAGS += -g
|
||||||
|
# do not use -pg with PGI compilers
|
||||||
|
|
||||||
|
ifndef COMPILER
|
||||||
|
COMPILER=GCC_
|
||||||
|
endif
|
||||||
|
|
||||||
|
include ../${COMPILER}default.mk
|
||||||
0
sheet5/1/Makefile:Zone.Identifier
Normal file
0
sheet5/1/Makefile:Zone.Identifier
Normal file
99
sheet5/1/check_env.h
Normal file
99
sheet5/1/check_env.h
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#include <omp.h>
|
||||||
|
#endif
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
//#####################################
|
||||||
|
// G.Haase
|
||||||
|
// See https://sourceforge.net/p/predef/wiki/Compilers/
|
||||||
|
// http://www.cplusplus.com/doc/tutorial/preprocessor/
|
||||||
|
// also: export OMP_DISPLAY_ENV=VERBOSE
|
||||||
|
//#####################################
|
||||||
|
/** Checks for compilers, its versions, threads etc.
|
||||||
|
*
|
||||||
|
@param[in] argc number of command line arguemnts
|
||||||
|
@param[in] argv command line arguments as array of C-strings
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
void check_env(T argc, char const *argv[])
|
||||||
|
{
|
||||||
|
std::cout << "\n#######################################################################\n";
|
||||||
|
std::cout << "Code :";
|
||||||
|
for (T k = 0; k < argc; ++k) std::cout << " " << argv[k];
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
// compiler: https://sourceforge.net/p/predef/wiki/Compilers/
|
||||||
|
std::cout << "Compiler: ";
|
||||||
|
#if defined __INTEL_COMPILER
|
||||||
|
#pragma message(" ########## INTEL ###############")
|
||||||
|
std::cout << "INTEL " << __INTEL_COMPILER;
|
||||||
|
// Ignore warnings for #pragma acc unrecognice
|
||||||
|
#pragma warning disable 161
|
||||||
|
// Ignore warnings for #pragma omp unrecognice
|
||||||
|
#pragma warning disable 3180
|
||||||
|
|
||||||
|
#elif defined __PGI
|
||||||
|
#pragma message(" ########## PGI ###############")
|
||||||
|
std::cout << "PGI " << __PGIC__ << "." << __PGIC_MINOR__ << "." << __PGIC_PATCHLEVEL__;
|
||||||
|
#elif defined __clang__
|
||||||
|
#pragma message(" ########## CLANG ###############")
|
||||||
|
std::cout << "CLANG " << __clang_major__ << "." << __clang_minor__ << "."; // << __clang_patchlevel__;
|
||||||
|
#elif defined __GNUC__
|
||||||
|
#pragma message(" ########## Gnu ###############")
|
||||||
|
std::cout << "Gnu " << __GNUC__ << "." << __GNUC_MINOR__ << "." << __GNUC_PATCHLEVEL__;
|
||||||
|
#else
|
||||||
|
#pragma message(" ########## unknown Compiler ###############")
|
||||||
|
std::cout << "unknown";
|
||||||
|
#endif
|
||||||
|
std::cout << " C++ standard: " << __cplusplus << std::endl;
|
||||||
|
|
||||||
|
// Parallel environments
|
||||||
|
std::cout << "Parallel: ";
|
||||||
|
#if defined MPI_VERSION
|
||||||
|
#pragma message(" ########## MPI ###############")
|
||||||
|
#ifdef OPEN_MPI
|
||||||
|
std::cout << "OpenMPI ";
|
||||||
|
#else
|
||||||
|
std::cout << "MPI ";
|
||||||
|
#endif
|
||||||
|
std::cout << MPI_VERSION << "." << MPI_SUBVERSION << " ";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _OPENMP
|
||||||
|
//https://www.openmp.org/specifications/
|
||||||
|
//https://stackoverflow.com/questions/1304363/how-to-check-the-version-of-openmp-on-linux
|
||||||
|
std::unordered_map<unsigned, std::string> const map{
|
||||||
|
{200505, "2.5"}, {200805, "3.0"}, {201107, "3.1"}, {201307, "4.0"}, {201511, "4.5"}, {201611, "5.0"}, {201811, "5.0"}};
|
||||||
|
#pragma message(" ########## OPENMP ###############")
|
||||||
|
//std::cout << _OPENMP;
|
||||||
|
std::cout << "OpenMP ";
|
||||||
|
try {
|
||||||
|
std::cout << map.at(_OPENMP);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
std::cout << _OPENMP;
|
||||||
|
}
|
||||||
|
#pragma omp parallel
|
||||||
|
{
|
||||||
|
#pragma omp master
|
||||||
|
{
|
||||||
|
const int nn = omp_get_num_threads(); // OpenMP
|
||||||
|
std::cout << " ---> " << nn << " Threads ";
|
||||||
|
}
|
||||||
|
#pragma omp barrier
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#ifdef _OPENACC
|
||||||
|
#pragma message(" ########## OPENACC ###############")
|
||||||
|
std::cout << "OpenACC ";
|
||||||
|
#endif
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "Date : " << __DATE__ << " " << __TIME__;
|
||||||
|
std::cout << "\n#######################################################################\n";
|
||||||
|
}
|
||||||
|
// HG
|
||||||
|
|
||||||
0
sheet5/1/check_env.h:Zone.Identifier
Normal file
0
sheet5/1/check_env.h:Zone.Identifier
Normal file
BIN
sheet5/1/main.GCC_
Executable file
BIN
sheet5/1/main.GCC_
Executable file
Binary file not shown.
203
sheet5/1/main.cpp
Normal file
203
sheet5/1/main.cpp
Normal file
|
|
@ -0,0 +1,203 @@
|
||||||
|
#include "check_env.h"
|
||||||
|
#include "mylib.h"
|
||||||
|
#include <cstdlib> // atoi()
|
||||||
|
#include <cstring> // strncmp()
|
||||||
|
#include <ctime>
|
||||||
|
#include <iostream>
|
||||||
|
#include <omp.h> // OpenMP
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <cmath>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
void benchmark(vector<double> &x, vector<double> &y, unsigned int N, unsigned int NLOOPS)
|
||||||
|
{
|
||||||
|
double sk = 0.0;
|
||||||
|
for (int i = 0; i < NLOOPS; ++i)
|
||||||
|
{
|
||||||
|
sk += scalar(x, y);
|
||||||
|
// or scalar_trans(x,y) / norm(x) if you want
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
//int const NLOOPS = 5; // chose a value such that the benchmark runs at least 10 sec.
|
||||||
|
unsigned int N = 5000001;
|
||||||
|
int const NLOOPS = 5; // chose a value such that the benchmark runs at least 10 sec.
|
||||||
|
//unsigned int N = 5000001;
|
||||||
|
//##########################################################################
|
||||||
|
// Read Parameter from command line (C++ style)
|
||||||
|
cout << "Checking command line parameters for: -n <number> " << endl;
|
||||||
|
for (int i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
cout << " arg[" << i << "] = " << argv[i] << endl;
|
||||||
|
string ss(argv[i]);
|
||||||
|
if ("-n"==ss && i + 1 < argc) // found "-n" followed by another parameter
|
||||||
|
{
|
||||||
|
N = static_cast<unsigned int>(atoi(argv[i + 1]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cout << "Corect call: " << argv[0] << " -n <number>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << "\nN = " << N << endl;
|
||||||
|
|
||||||
|
check_env(argc, argv);
|
||||||
|
//########################################################################
|
||||||
|
int nthreads; // OpenMP
|
||||||
|
#pragma omp parallel default(none) shared(cout,nthreads)
|
||||||
|
{
|
||||||
|
int const th_id = omp_get_thread_num(); // OpenMP
|
||||||
|
int const nthrds = omp_get_num_threads(); // OpenMP
|
||||||
|
stringstream ss;
|
||||||
|
ss << "C++: Hello World from thread " << th_id << " / " << nthrds << endl;
|
||||||
|
#pragma omp critical
|
||||||
|
{
|
||||||
|
cout << ss.str(); // output to a shared ressource
|
||||||
|
}
|
||||||
|
#pragma omp master
|
||||||
|
nthreads = nthrds; // transfer nn to to master thread
|
||||||
|
}
|
||||||
|
cout << " " << nthreads << " threads have been started." << endl;
|
||||||
|
|
||||||
|
//##########################################################################
|
||||||
|
// Memory allocation
|
||||||
|
cout << "Memory allocation\n";
|
||||||
|
|
||||||
|
vector<double> x(N), y(N);
|
||||||
|
|
||||||
|
cout.precision(2);
|
||||||
|
cout << 2.0 * N *sizeof(x[0]) / 1024 / 1024 / 1024 << " GByte Memory allocated\n";
|
||||||
|
cout.precision(6);
|
||||||
|
|
||||||
|
//##########################################################################
|
||||||
|
// Data initialization
|
||||||
|
// Special: x_i = i+1; y_i = 1/x_i ==> <x,y> == N
|
||||||
|
for (unsigned int i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
x[i] = i + 1;
|
||||||
|
y[i] = 1.0 / x[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
//##########################################################################
|
||||||
|
cout << "\nStart Benchmarking\n";
|
||||||
|
|
||||||
|
// Do calculation
|
||||||
|
double tstart = omp_get_wtime(); // OpenMP
|
||||||
|
|
||||||
|
double sk(0.0);
|
||||||
|
for (int i = 0; i < NLOOPS; ++i)
|
||||||
|
{
|
||||||
|
sk = scalar(x, y);
|
||||||
|
sk = scalar_trans(x, y);
|
||||||
|
//sk = norm(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
double t1 = omp_get_wtime() - tstart; // OpenMP
|
||||||
|
t1 /= NLOOPS; // divide by number of function calls
|
||||||
|
|
||||||
|
//##########################################################################
|
||||||
|
// Check the correct result
|
||||||
|
cout << "\n <x,y> = " << sk << endl;
|
||||||
|
if (static_cast<unsigned int>(sk) != N)
|
||||||
|
{
|
||||||
|
cout << " !! W R O N G result !!\n";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
//##########################################################################
|
||||||
|
// Timings and Performance
|
||||||
|
cout << endl;
|
||||||
|
cout.precision(2);
|
||||||
|
cout << "Timing in sec. : " << t1 << endl;
|
||||||
|
cout << "GFLOPS : " << 2.0 * N / t1 / 1024 / 1024 / 1024 << endl;
|
||||||
|
cout << "GiByte/s : " << 2.0 * N / t1 / 1024 / 1024 / 1024 * sizeof(x[0]) << endl;
|
||||||
|
|
||||||
|
//#########################################################################
|
||||||
|
|
||||||
|
cout << "\n Try the reduction with an STL-vektor \n";
|
||||||
|
|
||||||
|
auto vr = reduction_vec(100);
|
||||||
|
cout << "done\n";
|
||||||
|
cout << vr << endl;
|
||||||
|
|
||||||
|
N=2;
|
||||||
|
//Data (re-)inizialiion
|
||||||
|
for (unsigned int i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
x[i] = i + 1;
|
||||||
|
y[i] = 1.0 / x[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int proc_count = omp_get_num_procs();
|
||||||
|
cout << "Number of available processors: " << proc_count << endl;
|
||||||
|
|
||||||
|
for(int j=1; j<=proc_count; j++)
|
||||||
|
{
|
||||||
|
omp_set_num_threads(j);
|
||||||
|
cout << "used threads: "<< j << endl;
|
||||||
|
|
||||||
|
|
||||||
|
omp_set_schedule(omp_sched_static, 0);
|
||||||
|
tstart = omp_get_wtime();
|
||||||
|
benchmark(x, y, N, NLOOPS);
|
||||||
|
t1 = omp_get_wtime()/NLOOPS;
|
||||||
|
cout << "static (chunk 0) "<< (t1-tstart) << endl;
|
||||||
|
for(int i=0; i<= 5; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
int chunk = 1 << i;
|
||||||
|
cout << "chunk size: "<< chunk << endl;
|
||||||
|
|
||||||
|
// STATIC
|
||||||
|
omp_set_schedule(omp_sched_static, chunk);
|
||||||
|
tstart = omp_get_wtime();
|
||||||
|
benchmark(x, y, N, NLOOPS);
|
||||||
|
t1 = omp_get_wtime()/NLOOPS;
|
||||||
|
std::cout << "static: " << (t1 - tstart) << " s\n";
|
||||||
|
|
||||||
|
// DYNAMIC
|
||||||
|
omp_set_schedule(omp_sched_dynamic, chunk);
|
||||||
|
tstart = omp_get_wtime();
|
||||||
|
benchmark(x, y, N, NLOOPS);
|
||||||
|
t1 = omp_get_wtime()/NLOOPS;
|
||||||
|
std::cout << "dynamic: " << (t1 - tstart) << " s\n";
|
||||||
|
|
||||||
|
// GUIDED
|
||||||
|
omp_set_schedule(omp_sched_guided, chunk);
|
||||||
|
tstart = omp_get_wtime();
|
||||||
|
benchmark(x, y, N, NLOOPS);
|
||||||
|
t1 = omp_get_wtime()/NLOOPS;
|
||||||
|
std::cout << "guided: " << (t1 - tstart) << " s\n";
|
||||||
|
|
||||||
|
// AUTO
|
||||||
|
omp_set_schedule(omp_sched_auto, chunk);
|
||||||
|
tstart = omp_get_wtime();
|
||||||
|
benchmark(x, y, N, NLOOPS);
|
||||||
|
t1 = omp_get_wtime()/NLOOPS;
|
||||||
|
std::cout << "auto: " << (t1 - tstart) << " s\n";
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cout << scalar_parrallel_env(x,y) << endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
vector<int> vec = reduction_vec_append(N);
|
||||||
|
for(int i=0; i< N; i++)
|
||||||
|
{
|
||||||
|
cout << vec[i] << ", ";
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} // memory for x and y will be deallocated their destructors
|
||||||
|
|
||||||
0
sheet5/1/main.cpp:Zone.Identifier
Normal file
0
sheet5/1/main.cpp:Zone.Identifier
Normal file
BIN
sheet5/1/main.o
Normal file
BIN
sheet5/1/main.o
Normal file
Binary file not shown.
136
sheet5/1/mylib.cpp
Normal file
136
sheet5/1/mylib.cpp
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
#include "mylib.h"
|
||||||
|
#include <cassert> // assert()
|
||||||
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
|
#include <functional> // multiplies<>{}
|
||||||
|
#include <list>
|
||||||
|
#include <numeric> // iota()
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#include <omp.h>
|
||||||
|
#endif
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
double scalar(vector<double> const &x, vector<double> const &y)
|
||||||
|
{
|
||||||
|
assert(x.size() == y.size()); // switch off via compile flag: -DNDEBUG
|
||||||
|
size_t const N = x.size();
|
||||||
|
double sum = 0.0;
|
||||||
|
if (!omp_in_parallel())
|
||||||
|
{
|
||||||
|
// Safe to start a parallel region
|
||||||
|
#pragma omp parallel for default(none) shared(x,y,N) reduction(+:sum) schedule(runtime)
|
||||||
|
for (size_t i = 0; i < N; ++i)
|
||||||
|
sum += x[i] * y[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Already inside parallel region: do it sequentially to avoid nested parallelism
|
||||||
|
for (size_t i = 0; i < N; ++i)
|
||||||
|
sum += x[i] * y[i];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double scalar_parrallel_env(vector<double> const &x, vector<double> const &y)
|
||||||
|
{
|
||||||
|
assert(x.size() == y.size()); // switch off via compile flag: -DNDEBUG
|
||||||
|
size_t const N = x.size();
|
||||||
|
double sum = 0.0;
|
||||||
|
|
||||||
|
|
||||||
|
// Safe to start a parallel region
|
||||||
|
#pragma omp parallel default(none) shared(x,y,N,cout) reduction(+:sum)
|
||||||
|
{
|
||||||
|
int tid = omp_get_thread_num();
|
||||||
|
int threadCount = omp_get_num_threads();
|
||||||
|
cout << threadCount << endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (size_t i = tid*N/threadCount; i < tid*(N + 1)/threadCount; ++i)
|
||||||
|
{
|
||||||
|
sum += x[i] * y[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
double norm(vector<double> const &x)
|
||||||
|
{
|
||||||
|
size_t const N = x.size();
|
||||||
|
double sum = 0.0;
|
||||||
|
#pragma omp parallel for default(none) shared(x,N) reduction(+:sum)
|
||||||
|
for (size_t i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
sum += x[i]*x[i];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
vector<int> reduction_vec(int n)
|
||||||
|
{
|
||||||
|
vector<int> vec(n);
|
||||||
|
#pragma omp parallel default(none) shared(cout) reduction(VecAdd:vec)
|
||||||
|
{
|
||||||
|
#pragma omp barrier
|
||||||
|
#pragma omp critical
|
||||||
|
cout << omp_get_thread_num() << " : " << vec.size() << endl;
|
||||||
|
#pragma omp barrier
|
||||||
|
iota( vec.begin(),vec.end(), omp_get_thread_num() );
|
||||||
|
#pragma omp barrier
|
||||||
|
|
||||||
|
}
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<int> reduction_vec_append(int n)
|
||||||
|
{
|
||||||
|
vector<int> vec(n);
|
||||||
|
#pragma omp parallel default(none) shared(cout,n) reduction(VecAppend:vec)
|
||||||
|
{
|
||||||
|
int tid = omp_get_thread_num();
|
||||||
|
|
||||||
|
vector<int> local(n);
|
||||||
|
iota(local.begin(), local.end(), tid);
|
||||||
|
|
||||||
|
#pragma omp critical
|
||||||
|
cout << tid << " : " << local.size() << endl;
|
||||||
|
|
||||||
|
vec = local;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
double scalar_trans(vector<double> const &x, vector<double> const &y)
|
||||||
|
{
|
||||||
|
assert(x.size() == y.size()); // switch off via compile flag: -DNDEBUG
|
||||||
|
vector<double> z(x.size());
|
||||||
|
//list<double> z(x.size()); // parallel for-loop on iterators not possible (missing 'operator-')
|
||||||
|
// c++-20 CLANG_, ONEAPI_:condition of OpenMP for loop must be a relational comparison
|
||||||
|
|
||||||
|
transform(cbegin(x),cend(x),cbegin(y),begin(z),std::multiplies<>{});
|
||||||
|
|
||||||
|
double sum = 0.0;
|
||||||
|
#pragma omp parallel for default(none) shared(z) reduction(+:sum)
|
||||||
|
for (auto pi = cbegin(z); pi!=cend(z); ++pi)
|
||||||
|
{
|
||||||
|
sum += *pi;
|
||||||
|
}
|
||||||
|
//for (auto val: z)
|
||||||
|
//{
|
||||||
|
//sum += val;
|
||||||
|
//}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
0
sheet5/1/mylib.cpp:Zone.Identifier
Normal file
0
sheet5/1/mylib.cpp:Zone.Identifier
Normal file
86
sheet5/1/mylib.h
Normal file
86
sheet5/1/mylib.h
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
#pragma once
|
||||||
|
#include <cassert>
|
||||||
|
#include <iomanip> // setw()
|
||||||
|
#include <iostream>
|
||||||
|
#include <omp.h>
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
/** Inner product
|
||||||
|
@param[in] x vector
|
||||||
|
@param[in] y vector
|
||||||
|
@return resulting Euclidian inner product <x,y>
|
||||||
|
*/
|
||||||
|
double scalar(std::vector<double> const &x, std::vector<double> const &y);
|
||||||
|
double scalar_trans(std::vector<double> const &x, std::vector<double> const &y);
|
||||||
|
double scalar_parrallel_env(std::vector<double> const &x, std::vector<double> const &y);
|
||||||
|
|
||||||
|
|
||||||
|
/** l2-norm
|
||||||
|
@param[in] x vector
|
||||||
|
@return resulting Euclidian norm
|
||||||
|
*/
|
||||||
|
double norm(std::vector<double> const &x);
|
||||||
|
|
||||||
|
/** Vector @p b adds its elements to vector @p a .
|
||||||
|
@param[in] a vector
|
||||||
|
@param[in] b vector
|
||||||
|
@return a+=b componentwise
|
||||||
|
*/
|
||||||
|
template<class T>
|
||||||
|
std::vector<T> &operator+=(std::vector<T> &a, std::vector<T> const &b)
|
||||||
|
{
|
||||||
|
assert(a.size()==b.size());
|
||||||
|
for (size_t k = 0; k < a.size(); ++k) {
|
||||||
|
a[k] += b[k];
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Declare the reduction operation in OpenMP for an STL-vector
|
||||||
|
// omp_out += omp_in requires operator+=(vector<int> &, vector<int> const &) from above
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// https://scc.ustc.edu.cn/zlsc/tc4600/intel/2016.0.109/compiler_c/common/core/GUID-7312910C-D175-4544-99C5-29C12D980744.htm
|
||||||
|
// https://gist.github.com/eruffaldi/7180bdec4c8c9a11f019dd0ba9a2d68c
|
||||||
|
// https://stackoverflow.com/questions/29633531/user-defined-reduction-on-vector-of-varying-size
|
||||||
|
// see also p.74ff in https://www.fz-juelich.de/ias/jsc/EN/AboutUs/Staff/Hagemeier_A/docs-parallel-programming/OpenMP-Slides.pdf
|
||||||
|
#pragma omp declare reduction(VecAdd : std::vector<int> : omp_out += omp_in) \
|
||||||
|
initializer (omp_priv=omp_orig)
|
||||||
|
|
||||||
|
|
||||||
|
#pragma omp declare reduction(VecAppend: std::vector<int> : omp_out.insert(omp_out.end(), omp_in.begin(), omp_in.end())) \
|
||||||
|
initializer (omp_priv=vector<int>())
|
||||||
|
|
||||||
|
// Templates are n o t possible, i.e. the reduction has to be declared fore a specified type.
|
||||||
|
//template <class T>
|
||||||
|
//#pragma omp declare reduction(VecAdd : std::vector<T> : omp_out += omp_in) initializer (omp_priv(omp_orig))
|
||||||
|
// MS: template nach #pragma !?
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
/** Test for vector reduction.
|
||||||
|
*
|
||||||
|
* The thread-private vectors of size @p n are initialized via @f$v_k^{tID}=tID+k@f$.
|
||||||
|
* Afterwards these vectors are accumulated, i.e.,
|
||||||
|
* @f$v_k= \sum_{tID=0}^{numThreads} v_k^{tID}@f$.
|
||||||
|
*
|
||||||
|
* @param[in] n size of global/private vector
|
||||||
|
* @return resulting global vector.
|
||||||
|
*/
|
||||||
|
std::vector<int> reduction_vec(int n);
|
||||||
|
std::vector<int> reduction_vec_append(int n);
|
||||||
|
|
||||||
|
|
||||||
|
/** Output of a vector.
|
||||||
|
@param[in,out] s output stream
|
||||||
|
@param[in] x vector
|
||||||
|
@return modified output stream
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
std::ostream &operator<<(std::ostream &s, std::vector<T> const &x)
|
||||||
|
{
|
||||||
|
for (auto const &v : x) s << std::setw(4) << v << " ";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
0
sheet5/1/mylib.h:Zone.Identifier
Normal file
0
sheet5/1/mylib.h:Zone.Identifier
Normal file
BIN
sheet5/1/mylib.o
Normal file
BIN
sheet5/1/mylib.o
Normal file
Binary file not shown.
70
sheet5/1/timing.h
Normal file
70
sheet5/1/timing.h
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
#pragma once
|
||||||
|
#include <chrono> // timing
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
|
using Clock = std::chrono::system_clock; //!< The wall clock timer chosen
|
||||||
|
//using Clock = std::chrono::high_resolution_clock;
|
||||||
|
using TPoint= std::chrono::time_point<Clock>;
|
||||||
|
|
||||||
|
// [Galowicz, C++17 STL Cookbook, p. 29]
|
||||||
|
inline
|
||||||
|
std::stack<TPoint> MyStopWatch; //!< starting time of stopwatch
|
||||||
|
|
||||||
|
/** Starts stopwatch timer.
|
||||||
|
* Use as @code tic(); myfunction(...) ; double tsec = toc(); @endcode
|
||||||
|
*
|
||||||
|
* The timining is allowed to be nested and the recent time is stored on top of the stack.
|
||||||
|
*
|
||||||
|
* @return recent time
|
||||||
|
* @see toc
|
||||||
|
*/
|
||||||
|
inline auto tic()
|
||||||
|
{
|
||||||
|
MyStopWatch.push(Clock::now());
|
||||||
|
return MyStopWatch.top();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the elapsed time from stopwatch.
|
||||||
|
*
|
||||||
|
* The time from top of the stack is used
|
||||||
|
* if time point @p t_b is not passed as input parameter.
|
||||||
|
* Use as @code tic(); myfunction(...) ; double tsec = toc(); @endcode
|
||||||
|
* or as @code auto t_b = tic(); myfunction(...) ; double tsec = toc(t_b); @endcode
|
||||||
|
* The last option is to be used in the case of
|
||||||
|
* non-nested but overlapping time measurements.
|
||||||
|
*
|
||||||
|
* @param[in] t_b start time of some stop watch
|
||||||
|
* @return elapsed time in seconds.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
inline double toc(TPoint const &t_b = MyStopWatch.top())
|
||||||
|
{
|
||||||
|
// https://en.cppreference.com/w/cpp/chrono/treat_as_floating_point
|
||||||
|
using Unit = std::chrono::seconds;
|
||||||
|
using FpSeconds = std::chrono::duration<double, Unit::period>;
|
||||||
|
auto t_e = Clock::now();
|
||||||
|
MyStopWatch.pop();
|
||||||
|
return FpSeconds(t_e-t_b).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
/** Executes function @p f and measures/prints elapsed wall clock time in seconds
|
||||||
|
*
|
||||||
|
* Call as
|
||||||
|
* @code measure("Time for (b = b + 1)", [&]() {
|
||||||
|
thrust::transform(b.begin(), b.end(), b.begin(), increment());
|
||||||
|
}); @endcode
|
||||||
|
*
|
||||||
|
* @param[in] label additional string to be printed with the measurement.
|
||||||
|
* @param[in] f function to execute.
|
||||||
|
* @author Therese Bösmüller, 2025
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
auto measure = [](const std::string& label, auto&& f) {
|
||||||
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
f();
|
||||||
|
auto stop = std::chrono::high_resolution_clock::now();
|
||||||
|
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count();
|
||||||
|
std::cout << label << ": " << duration << " microseconds" << std::endl;
|
||||||
|
}; // ';' is needed for a visible documentation of this lambda-function
|
||||||
0
sheet5/1/timing.h:Zone.Identifier
Normal file
0
sheet5/1/timing.h:Zone.Identifier
Normal file
16
sheet5/2/.vscode/c_cpp_properties.json
vendored
Normal file
16
sheet5/2/.vscode/c_cpp_properties.json
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "gnu++17",
|
||||||
|
"intelliSenseMode": "linux-gcc-x64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
59
sheet5/2/.vscode/settings.json
vendored
Normal file
59
sheet5/2/.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"iostream": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"bit": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"charconv": "cpp",
|
||||||
|
"chrono": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"compare": "cpp",
|
||||||
|
"concepts": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"list": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"format": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"numbers": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"span": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"typeinfo": "cpp",
|
||||||
|
"variant": "cpp"
|
||||||
|
}
|
||||||
|
}
|
||||||
0
sheet5/2/.vscode/settings.json:Zone.Identifier
vendored
Normal file
0
sheet5/2/.vscode/settings.json:Zone.Identifier
vendored
Normal file
39
sheet5/2/Makefile
Normal file
39
sheet5/2/Makefile
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#
|
||||||
|
# use GNU-Compiler tools
|
||||||
|
COMPILER=GCC_
|
||||||
|
# alternatively from the shell
|
||||||
|
# export COMPILER=GCC_
|
||||||
|
# or, alternatively from the shell
|
||||||
|
# make COMPILER=GCC_
|
||||||
|
|
||||||
|
# use Intel compilers
|
||||||
|
#COMPILER=ICC_
|
||||||
|
|
||||||
|
# use PGI compilers
|
||||||
|
# COMPILER=PGI_
|
||||||
|
|
||||||
|
# use CLANG compilers
|
||||||
|
# COMPILER=CLANG_
|
||||||
|
|
||||||
|
|
||||||
|
SOURCES = main.cpp file_io.cpp means.cpp
|
||||||
|
OBJECTS = $(SOURCES:.cpp=.o)
|
||||||
|
|
||||||
|
PROGRAM = main.${COMPILER}
|
||||||
|
|
||||||
|
# uncomment the next to lines for debugging and detailed performance analysis
|
||||||
|
CXXFLAGS += -g
|
||||||
|
LINKFLAGS += -g
|
||||||
|
# do not use -pg with PGI compilers
|
||||||
|
|
||||||
|
ifndef COMPILER
|
||||||
|
COMPILER=GCC_
|
||||||
|
endif
|
||||||
|
|
||||||
|
include ../${COMPILER}default.mk
|
||||||
|
|
||||||
|
|
||||||
|
task:
|
||||||
|
@pdflatex task
|
||||||
|
@pdflatex task
|
||||||
|
|
||||||
0
sheet5/2/Makefile:Zone.Identifier
Normal file
0
sheet5/2/Makefile:Zone.Identifier
Normal file
500
sheet5/2/data_1.txt
Normal file
500
sheet5/2/data_1.txt
Normal file
|
|
@ -0,0 +1,500 @@
|
||||||
|
141
|
||||||
|
261
|
||||||
|
87
|
||||||
|
430
|
||||||
|
258
|
||||||
|
298
|
||||||
|
425
|
||||||
|
120
|
||||||
|
496
|
||||||
|
707
|
||||||
|
244
|
||||||
|
786
|
||||||
|
75
|
||||||
|
394
|
||||||
|
4
|
||||||
|
221
|
||||||
|
2
|
||||||
|
190
|
||||||
|
143
|
||||||
|
269
|
||||||
|
175
|
||||||
|
139
|
||||||
|
599
|
||||||
|
902
|
||||||
|
940
|
||||||
|
222
|
||||||
|
483
|
||||||
|
377
|
||||||
|
524
|
||||||
|
265
|
||||||
|
69
|
||||||
|
437
|
||||||
|
174
|
||||||
|
27
|
||||||
|
955
|
||||||
|
431
|
||||||
|
962
|
||||||
|
763
|
||||||
|
8
|
||||||
|
681
|
||||||
|
706
|
||||||
|
646
|
||||||
|
553
|
||||||
|
219
|
||||||
|
773
|
||||||
|
229
|
||||||
|
371
|
||||||
|
891
|
||||||
|
857
|
||||||
|
403
|
||||||
|
319
|
||||||
|
609
|
||||||
|
911
|
||||||
|
910
|
||||||
|
592
|
||||||
|
333
|
||||||
|
854
|
||||||
|
443
|
||||||
|
905
|
||||||
|
34
|
||||||
|
533
|
||||||
|
717
|
||||||
|
180
|
||||||
|
337
|
||||||
|
188
|
||||||
|
322
|
||||||
|
404
|
||||||
|
549
|
||||||
|
49
|
||||||
|
553
|
||||||
|
275
|
||||||
|
242
|
||||||
|
244
|
||||||
|
155
|
||||||
|
957
|
||||||
|
936
|
||||||
|
819
|
||||||
|
729
|
||||||
|
176
|
||||||
|
361
|
||||||
|
189
|
||||||
|
2
|
||||||
|
317
|
||||||
|
700
|
||||||
|
626
|
||||||
|
544
|
||||||
|
440
|
||||||
|
288
|
||||||
|
502
|
||||||
|
762
|
||||||
|
763
|
||||||
|
577
|
||||||
|
748
|
||||||
|
646
|
||||||
|
124
|
||||||
|
505
|
||||||
|
348
|
||||||
|
93
|
||||||
|
148
|
||||||
|
199
|
||||||
|
673
|
||||||
|
432
|
||||||
|
695
|
||||||
|
257
|
||||||
|
10
|
||||||
|
533
|
||||||
|
280
|
||||||
|
947
|
||||||
|
907
|
||||||
|
393
|
||||||
|
25
|
||||||
|
672
|
||||||
|
838
|
||||||
|
972
|
||||||
|
57
|
||||||
|
451
|
||||||
|
583
|
||||||
|
687
|
||||||
|
720
|
||||||
|
651
|
||||||
|
727
|
||||||
|
374
|
||||||
|
582
|
||||||
|
117
|
||||||
|
58
|
||||||
|
980
|
||||||
|
285
|
||||||
|
595
|
||||||
|
963
|
||||||
|
186
|
||||||
|
194
|
||||||
|
342
|
||||||
|
933
|
||||||
|
391
|
||||||
|
274
|
||||||
|
152
|
||||||
|
398
|
||||||
|
375
|
||||||
|
132
|
||||||
|
436
|
||||||
|
92
|
||||||
|
615
|
||||||
|
11
|
||||||
|
574
|
||||||
|
790
|
||||||
|
236
|
||||||
|
449
|
||||||
|
570
|
||||||
|
62
|
||||||
|
497
|
||||||
|
643
|
||||||
|
222
|
||||||
|
838
|
||||||
|
972
|
||||||
|
847
|
||||||
|
506
|
||||||
|
279
|
||||||
|
747
|
||||||
|
237
|
||||||
|
958
|
||||||
|
621
|
||||||
|
601
|
||||||
|
173
|
||||||
|
91
|
||||||
|
256
|
||||||
|
859
|
||||||
|
912
|
||||||
|
700
|
||||||
|
726
|
||||||
|
230
|
||||||
|
577
|
||||||
|
811
|
||||||
|
404
|
||||||
|
989
|
||||||
|
90
|
||||||
|
321
|
||||||
|
512
|
||||||
|
61
|
||||||
|
726
|
||||||
|
557
|
||||||
|
530
|
||||||
|
830
|
||||||
|
859
|
||||||
|
790
|
||||||
|
318
|
||||||
|
453
|
||||||
|
753
|
||||||
|
110
|
||||||
|
110
|
||||||
|
270
|
||||||
|
525
|
||||||
|
973
|
||||||
|
711
|
||||||
|
312
|
||||||
|
292
|
||||||
|
851
|
||||||
|
912
|
||||||
|
640
|
||||||
|
256
|
||||||
|
89
|
||||||
|
839
|
||||||
|
585
|
||||||
|
949
|
||||||
|
62
|
||||||
|
585
|
||||||
|
286
|
||||||
|
828
|
||||||
|
191
|
||||||
|
443
|
||||||
|
394
|
||||||
|
827
|
||||||
|
677
|
||||||
|
208
|
||||||
|
319
|
||||||
|
134
|
||||||
|
672
|
||||||
|
571
|
||||||
|
170
|
||||||
|
148
|
||||||
|
477
|
||||||
|
909
|
||||||
|
553
|
||||||
|
33
|
||||||
|
54
|
||||||
|
806
|
||||||
|
452
|
||||||
|
383
|
||||||
|
790
|
||||||
|
365
|
||||||
|
533
|
||||||
|
712
|
||||||
|
872
|
||||||
|
329
|
||||||
|
651
|
||||||
|
975
|
||||||
|
76
|
||||||
|
588
|
||||||
|
414
|
||||||
|
310
|
||||||
|
264
|
||||||
|
759
|
||||||
|
996
|
||||||
|
187
|
||||||
|
782
|
||||||
|
196
|
||||||
|
993
|
||||||
|
803
|
||||||
|
425
|
||||||
|
729
|
||||||
|
499
|
||||||
|
809
|
||||||
|
357
|
||||||
|
74
|
||||||
|
591
|
||||||
|
911
|
||||||
|
194
|
||||||
|
433
|
||||||
|
750
|
||||||
|
40
|
||||||
|
947
|
||||||
|
764
|
||||||
|
559
|
||||||
|
184
|
||||||
|
498
|
||||||
|
518
|
||||||
|
995
|
||||||
|
855
|
||||||
|
963
|
||||||
|
679
|
||||||
|
404
|
||||||
|
935
|
||||||
|
480
|
||||||
|
232
|
||||||
|
397
|
||||||
|
706
|
||||||
|
559
|
||||||
|
757
|
||||||
|
996
|
||||||
|
963
|
||||||
|
536
|
||||||
|
964
|
||||||
|
116
|
||||||
|
52
|
||||||
|
305
|
||||||
|
581
|
||||||
|
531
|
||||||
|
902
|
||||||
|
541
|
||||||
|
432
|
||||||
|
543
|
||||||
|
713
|
||||||
|
17
|
||||||
|
801
|
||||||
|
143
|
||||||
|
479
|
||||||
|
257
|
||||||
|
370
|
||||||
|
662
|
||||||
|
170
|
||||||
|
279
|
||||||
|
199
|
||||||
|
196
|
||||||
|
327
|
||||||
|
881
|
||||||
|
472
|
||||||
|
404
|
||||||
|
180
|
||||||
|
969
|
||||||
|
408
|
||||||
|
845
|
||||||
|
616
|
||||||
|
377
|
||||||
|
878
|
||||||
|
785
|
||||||
|
465
|
||||||
|
814
|
||||||
|
899
|
||||||
|
430
|
||||||
|
335
|
||||||
|
597
|
||||||
|
902
|
||||||
|
703
|
||||||
|
378
|
||||||
|
735
|
||||||
|
955
|
||||||
|
543
|
||||||
|
541
|
||||||
|
312
|
||||||
|
72
|
||||||
|
182
|
||||||
|
93
|
||||||
|
464
|
||||||
|
10
|
||||||
|
916
|
||||||
|
643
|
||||||
|
2
|
||||||
|
31
|
||||||
|
209
|
||||||
|
455
|
||||||
|
128
|
||||||
|
9
|
||||||
|
728
|
||||||
|
355
|
||||||
|
781
|
||||||
|
437
|
||||||
|
437
|
||||||
|
50
|
||||||
|
50
|
||||||
|
92
|
||||||
|
595
|
||||||
|
242
|
||||||
|
842
|
||||||
|
858
|
||||||
|
964
|
||||||
|
489
|
||||||
|
221
|
||||||
|
227
|
||||||
|
537
|
||||||
|
763
|
||||||
|
348
|
||||||
|
462
|
||||||
|
640
|
||||||
|
918
|
||||||
|
162
|
||||||
|
716
|
||||||
|
578
|
||||||
|
434
|
||||||
|
885
|
||||||
|
394
|
||||||
|
179
|
||||||
|
634
|
||||||
|
625
|
||||||
|
328
|
||||||
|
803
|
||||||
|
1000
|
||||||
|
981
|
||||||
|
128
|
||||||
|
233
|
||||||
|
24
|
||||||
|
608
|
||||||
|
111
|
||||||
|
408
|
||||||
|
885
|
||||||
|
549
|
||||||
|
370
|
||||||
|
209
|
||||||
|
441
|
||||||
|
957
|
||||||
|
125
|
||||||
|
471
|
||||||
|
857
|
||||||
|
44
|
||||||
|
692
|
||||||
|
979
|
||||||
|
284
|
||||||
|
134
|
||||||
|
686
|
||||||
|
910
|
||||||
|
611
|
||||||
|
900
|
||||||
|
194
|
||||||
|
755
|
||||||
|
347
|
||||||
|
419
|
||||||
|
156
|
||||||
|
820
|
||||||
|
625
|
||||||
|
739
|
||||||
|
806
|
||||||
|
68
|
||||||
|
951
|
||||||
|
498
|
||||||
|
756
|
||||||
|
743
|
||||||
|
832
|
||||||
|
157
|
||||||
|
458
|
||||||
|
619
|
||||||
|
933
|
||||||
|
836
|
||||||
|
896
|
||||||
|
583
|
||||||
|
583
|
||||||
|
855
|
||||||
|
35
|
||||||
|
886
|
||||||
|
408
|
||||||
|
37
|
||||||
|
747
|
||||||
|
155
|
||||||
|
144
|
||||||
|
606
|
||||||
|
255
|
||||||
|
325
|
||||||
|
402
|
||||||
|
407
|
||||||
|
387
|
||||||
|
610
|
||||||
|
167
|
||||||
|
189
|
||||||
|
95
|
||||||
|
324
|
||||||
|
770
|
||||||
|
235
|
||||||
|
741
|
||||||
|
693
|
||||||
|
825
|
||||||
|
828
|
||||||
|
294
|
||||||
|
310
|
||||||
|
524
|
||||||
|
326
|
||||||
|
832
|
||||||
|
811
|
||||||
|
557
|
||||||
|
263
|
||||||
|
681
|
||||||
|
234
|
||||||
|
457
|
||||||
|
385
|
||||||
|
539
|
||||||
|
992
|
||||||
|
756
|
||||||
|
981
|
||||||
|
235
|
||||||
|
529
|
||||||
|
52
|
||||||
|
757
|
||||||
|
602
|
||||||
|
858
|
||||||
|
989
|
||||||
|
930
|
||||||
|
410
|
||||||
|
1
|
||||||
|
541
|
||||||
|
208
|
||||||
|
220
|
||||||
|
326
|
||||||
|
96
|
||||||
|
748
|
||||||
|
749
|
||||||
|
544
|
||||||
|
339
|
||||||
|
833
|
||||||
|
553
|
||||||
|
958
|
||||||
|
893
|
||||||
|
357
|
||||||
|
547
|
||||||
|
347
|
||||||
|
623
|
||||||
|
797
|
||||||
|
746
|
||||||
|
126
|
||||||
|
823
|
||||||
|
26
|
||||||
|
415
|
||||||
|
732
|
||||||
|
782
|
||||||
|
368
|
||||||
0
sheet5/2/data_1.txt:Zone.Identifier
Normal file
0
sheet5/2/data_1.txt:Zone.Identifier
Normal file
60
sheet5/2/file_io.cbp
Normal file
60
sheet5/2/file_io.cbp
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||||
|
<CodeBlocks_project_file>
|
||||||
|
<FileVersion major="1" minor="6" />
|
||||||
|
<Project>
|
||||||
|
<Option title="file_io" />
|
||||||
|
<Option pch_mode="2" />
|
||||||
|
<Option compiler="gcc" />
|
||||||
|
<Build>
|
||||||
|
<Target title="Debug">
|
||||||
|
<Option output="bin/Debug/file_io" prefix_auto="1" extension_auto="1" />
|
||||||
|
<Option object_output="obj/Debug/" />
|
||||||
|
<Option type="1" />
|
||||||
|
<Option compiler="gcc" />
|
||||||
|
<Compiler>
|
||||||
|
<Add option="-g" />
|
||||||
|
</Compiler>
|
||||||
|
</Target>
|
||||||
|
<Target title="Release">
|
||||||
|
<Option output="bin/Release/file_io" prefix_auto="1" extension_auto="1" />
|
||||||
|
<Option object_output="obj/Release/" />
|
||||||
|
<Option type="1" />
|
||||||
|
<Option compiler="gcc" />
|
||||||
|
<Compiler>
|
||||||
|
<Add option="-O2" />
|
||||||
|
</Compiler>
|
||||||
|
<Linker>
|
||||||
|
<Add option="-s" />
|
||||||
|
</Linker>
|
||||||
|
</Target>
|
||||||
|
</Build>
|
||||||
|
<Compiler>
|
||||||
|
<Add option="-Wshadow" />
|
||||||
|
<Add option="-Winit-self" />
|
||||||
|
<Add option="-Wunreachable-code" />
|
||||||
|
<Add option="-pedantic" />
|
||||||
|
<Add option="-std=c++11" />
|
||||||
|
<Add option="-Wextra" />
|
||||||
|
<Add option="-Wall" />
|
||||||
|
<Add option="-fexceptions" />
|
||||||
|
</Compiler>
|
||||||
|
<Unit filename="file_io.cpp" />
|
||||||
|
<Unit filename="file_io.h" />
|
||||||
|
<Unit filename="main.cpp" />
|
||||||
|
<Extensions>
|
||||||
|
<envvars />
|
||||||
|
<code_completion />
|
||||||
|
<lib_finder disable_auto="1" />
|
||||||
|
<debugger />
|
||||||
|
<DoxyBlocks>
|
||||||
|
<comment_style block="0" line="0" />
|
||||||
|
<doxyfile_project />
|
||||||
|
<doxyfile_build extract_all="1" />
|
||||||
|
<doxyfile_warnings />
|
||||||
|
<doxyfile_output />
|
||||||
|
<doxyfile_dot />
|
||||||
|
<general use_at_in_tags="1" />
|
||||||
|
</DoxyBlocks>
|
||||||
|
</Extensions>
|
||||||
|
</Project>
|
||||||
|
</CodeBlocks_project_file>
|
||||||
0
sheet5/2/file_io.cbp:Zone.Identifier
Normal file
0
sheet5/2/file_io.cbp:Zone.Identifier
Normal file
65
sheet5/2/file_io.cpp
Normal file
65
sheet5/2/file_io.cpp
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
#include "file_io.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
// [Str10, p.364]
|
||||||
|
void fill_vector(istream& istr, vector<short>& v)
|
||||||
|
{
|
||||||
|
double d=0;
|
||||||
|
while ( istr >> d) v.push_back(d); // Einlesen
|
||||||
|
if (!istr.eof())
|
||||||
|
{ // Fehlerbehandlung
|
||||||
|
cout << " Error handling \n";
|
||||||
|
if ( istr.bad() ) throw runtime_error("Schwerer Fehler in istr");
|
||||||
|
if ( istr.fail() ) // Versuch des Aufraeumens
|
||||||
|
{
|
||||||
|
cout << " Failed in reading all data.\n";
|
||||||
|
istr.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.shrink_to_fit(); // C++11
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void read_vector_from_file(const string& file_name, vector<short>& v)
|
||||||
|
{
|
||||||
|
ifstream fin(file_name); // Oeffne das File im ASCII-Modus
|
||||||
|
if( fin.is_open() ) // File gefunden:
|
||||||
|
{
|
||||||
|
v.clear(); // Vektor leeren
|
||||||
|
fill_vector(fin, v);
|
||||||
|
}
|
||||||
|
else // File nicht gefunden:
|
||||||
|
{
|
||||||
|
cout << "\nFile " << file_name << " has not been found.\n\n" ;
|
||||||
|
assert( fin.is_open() && "File not found." ); // exeption handling for the poor programmer
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_vector_to_file(const string& file_name, const vector<double>& v)
|
||||||
|
{
|
||||||
|
ofstream fout(file_name); // Oeffne das File im ASCII-Modus
|
||||||
|
if( fout.is_open() )
|
||||||
|
{
|
||||||
|
for (unsigned int k=0; k<v.size(); ++k)
|
||||||
|
{
|
||||||
|
fout << v.at(k) << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cout << "\nFile " << file_name << " has not been opened.\n\n" ;
|
||||||
|
assert( fout.is_open() && "File not opened." ); // exeption handling for the poor programmer
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
0
sheet5/2/file_io.cpp:Zone.Identifier
Normal file
0
sheet5/2/file_io.cpp:Zone.Identifier
Normal file
40
sheet5/2/file_io.h
Normal file
40
sheet5/2/file_io.h
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef FILE_IO_H_INCLUDED
|
||||||
|
#define FILE_IO_H_INCLUDED
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
//using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function opens the ASCII-file named @p file_name and reads the
|
||||||
|
double data into the C++ vector @p v.
|
||||||
|
If the file @p file_name does not exist then the code stops with an appropriate message.
|
||||||
|
@param[in] file_name name of the ASCII-file
|
||||||
|
@param[out] v C++ vector with double values
|
||||||
|
*/
|
||||||
|
|
||||||
|
void read_vector_from_file(const std::string& file_name, std::vector<short>& v);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function opens the ASCII-file named @p file_name and rewrites its with the
|
||||||
|
double data from the C++ vector @p v.
|
||||||
|
If there are problems in opening/generating file @p file_name
|
||||||
|
then the code stops with an appropriate message.
|
||||||
|
@param[in] file_name name of the ASCII-file
|
||||||
|
@param[in] v C++ vector with double values
|
||||||
|
*/
|
||||||
|
|
||||||
|
void write_vector_to_file(const std::string& file_name, const std::vector<double>& v);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fills the double-vector @p v with data from an input stream @p istr until this input stream
|
||||||
|
ends regularily. The vector is cleared and its memory is automatically allocated.
|
||||||
|
@param[in] istr input stream
|
||||||
|
@param[out] v C++ vector with double values
|
||||||
|
@warning An exception is thrown in case of wrong data format or corrupted data.
|
||||||
|
*/
|
||||||
|
void fill_vector(std::istream& istr, std::vector<double>& v);
|
||||||
|
|
||||||
|
#endif // FILE_IO_H_INCLUDED
|
||||||
0
sheet5/2/file_io.h:Zone.Identifier
Normal file
0
sheet5/2/file_io.h:Zone.Identifier
Normal file
BIN
sheet5/2/file_io.o
Normal file
BIN
sheet5/2/file_io.o
Normal file
Binary file not shown.
BIN
sheet5/2/main.GCC_
Executable file
BIN
sheet5/2/main.GCC_
Executable file
Binary file not shown.
129
sheet5/2/main.cpp
Normal file
129
sheet5/2/main.cpp
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
#include "file_io.h"
|
||||||
|
#include "means.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <execution>
|
||||||
|
#include <omp.h>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
cout << "File einlesen." << endl;
|
||||||
|
|
||||||
|
const string name("data_1.txt"); // name of input file
|
||||||
|
const string name2("out_1.txt"); // name of output file
|
||||||
|
vector<short> a; //-2^15 to 2^15-1 fits the values from the file
|
||||||
|
double min, max, ar, ge, ha, std;
|
||||||
|
|
||||||
|
|
||||||
|
read_vector_from_file(name, a);
|
||||||
|
const unsigned size = a.size();
|
||||||
|
double t_omp_start = omp_get_wtime();
|
||||||
|
min = a[0];
|
||||||
|
max = a[0];
|
||||||
|
|
||||||
|
#pragma omp parallel for reduction(min:min) reduction(max:max)
|
||||||
|
for (int i = 0; i < static_cast<int>(size); ++i) {
|
||||||
|
if (a[i] < min)
|
||||||
|
{
|
||||||
|
min = a[i];
|
||||||
|
}
|
||||||
|
if (a[i] > max) {
|
||||||
|
max = a[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
means_vector(a, ar, ge, ha);
|
||||||
|
|
||||||
|
std = 0.0;
|
||||||
|
#pragma omp parallel for reduction(+:std)
|
||||||
|
for(unsigned int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
std += pow(a.at(i)-ar,2);
|
||||||
|
}
|
||||||
|
std = sqrt(std/size);
|
||||||
|
|
||||||
|
double t_omp_end = omp_get_wtime();
|
||||||
|
double time_omp = t_omp_end - t_omp_start;
|
||||||
|
|
||||||
|
cout << "min: " << min << ", max: " << max << endl;
|
||||||
|
cout << "Arithmetic mean: " << ar
|
||||||
|
<< ", geometric mean: " << ge
|
||||||
|
<< ", harmonic mean: " << ha << endl;
|
||||||
|
cout << "std: " << std << endl;
|
||||||
|
|
||||||
|
vector<double> results = {min, max, ar, ge, ha, std};
|
||||||
|
write_vector_to_file(name2, results);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//C++17 execution policies
|
||||||
|
|
||||||
|
double min_ep = 0.0, max_ep = 0.0, ar_ep = 0.0, ge_ep = 0.0, ha_ep = 0.0, std_ep = 0.0;
|
||||||
|
|
||||||
|
double t_ep_start = omp_get_wtime();
|
||||||
|
|
||||||
|
|
||||||
|
auto p = minmax_element(execution::par, a.begin(), a.end());
|
||||||
|
min_ep = *p.first;
|
||||||
|
max_ep = *p.second;
|
||||||
|
|
||||||
|
double sum_ep = reduce(
|
||||||
|
execution::par,
|
||||||
|
a.begin(), a.end(),
|
||||||
|
0.0
|
||||||
|
);
|
||||||
|
ar_ep = sum_ep / size;
|
||||||
|
|
||||||
|
ge_ep = transform_reduce(
|
||||||
|
execution::par,
|
||||||
|
a.begin(), a.end(),
|
||||||
|
1.0,
|
||||||
|
multiplies<>(),
|
||||||
|
[size](short x){
|
||||||
|
return pow((double)x, 1.0 / size);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
double sum_inv_ep = transform_reduce(
|
||||||
|
execution::par,
|
||||||
|
a.begin(), a.end(),
|
||||||
|
0.0,
|
||||||
|
plus<>(),
|
||||||
|
[](short x){ return 1.0 / (double)x; }
|
||||||
|
);
|
||||||
|
ha_ep = size / sum_inv_ep;
|
||||||
|
|
||||||
|
double sum_sq_ep = transform_reduce(
|
||||||
|
execution::par,
|
||||||
|
a.begin(), a.end(),
|
||||||
|
0.0,
|
||||||
|
plus<>(),
|
||||||
|
[ar_ep](short x){
|
||||||
|
double d = x - ar_ep;
|
||||||
|
return d * d;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
std_ep = sqrt(sum_sq_ep / size);
|
||||||
|
|
||||||
|
|
||||||
|
double t_ep_end = omp_get_wtime();
|
||||||
|
double time_ep = t_ep_end - t_ep_start;
|
||||||
|
|
||||||
|
cout << "min: " << min_ep << ", max: " << max_ep << endl;
|
||||||
|
cout << "Arithmetic mean: " << ar_ep
|
||||||
|
<< ", geometric mean: " << ge_ep
|
||||||
|
<< ", harmonic mean: " << ha_ep << endl;
|
||||||
|
cout << "std: " << std_ep << endl;
|
||||||
|
|
||||||
|
|
||||||
|
cout << "OpenMP per run: " << (time_omp) << endl;
|
||||||
|
cout << "Execution policy per run: " << (time_ep) << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
0
sheet5/2/main.cpp:Zone.Identifier
Normal file
0
sheet5/2/main.cpp:Zone.Identifier
Normal file
BIN
sheet5/2/main.o
Normal file
BIN
sheet5/2/main.o
Normal file
Binary file not shown.
37
sheet5/2/means.cpp
Normal file
37
sheet5/2/means.cpp
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
#include <vector>
|
||||||
|
#include <omp.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
void means(int a, int b, int c, double &ar, double &ge, double &ha) {
|
||||||
|
ar = (a+b+c) / 3.0;
|
||||||
|
|
||||||
|
|
||||||
|
ge = pow(a,1.0/3.0) * pow(b,1.0/3.0) * pow(c,1.0/3.0); //do it instead of pow(a*b*c,1.0/3.0) to prevent integer overflow
|
||||||
|
|
||||||
|
ha = 3.0 / (1.0/a +1.0/b +1.0/c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void means_vector(const vector<short> &input, double &ar, double &ge, double &ha) {
|
||||||
|
int size = input.size();
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
cout << "Empty input" << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ar = 0;
|
||||||
|
ge = 1;
|
||||||
|
ha = 0;
|
||||||
|
#pragma omp parallel for reduction(+:ar,ha) reduction(*:ge)
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
ar += input.at(i);
|
||||||
|
ge *= pow(input.at(i), 1.0 / size);
|
||||||
|
ha += 1.0 / input.at(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
ar /= size;
|
||||||
|
ha = size / ha;
|
||||||
|
}
|
||||||
0
sheet5/2/means.cpp:Zone.Identifier
Normal file
0
sheet5/2/means.cpp:Zone.Identifier
Normal file
9
sheet5/2/means.h
Normal file
9
sheet5/2/means.h
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef MEANS_H_INCLUDED
|
||||||
|
#define MEANS_H_INCLUDED
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
void means(int a, int b, int c, double &ar, double &ge, double &ha);
|
||||||
|
void means_vector(const std::vector<short> &input, double &ar, double &ge, double &ha);
|
||||||
|
|
||||||
|
#endif // MEANS_H_INCLUDED
|
||||||
0
sheet5/2/means.h:Zone.Identifier
Normal file
0
sheet5/2/means.h:Zone.Identifier
Normal file
BIN
sheet5/2/means.o
Normal file
BIN
sheet5/2/means.o
Normal file
Binary file not shown.
6
sheet5/2/out_1.txt
Normal file
6
sheet5/2/out_1.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
1
|
||||||
|
1000
|
||||||
|
498.184
|
||||||
|
364.412
|
||||||
|
95.6857
|
||||||
|
287.905
|
||||||
0
sheet5/2/out_1.txt:Zone.Identifier
Normal file
0
sheet5/2/out_1.txt:Zone.Identifier
Normal file
16
sheet5/3/.vscode/c_cpp_properties.json
vendored
Normal file
16
sheet5/3/.vscode/c_cpp_properties.json
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "gnu++17",
|
||||||
|
"intelliSenseMode": "linux-gcc-x64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
5
sheet5/3/.vscode/settings.json
vendored
Normal file
5
sheet5/3/.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"ostream": "cpp"
|
||||||
|
}
|
||||||
|
}
|
||||||
0
sheet5/3/.vscode/settings.json:Zone.Identifier
vendored
Normal file
0
sheet5/3/.vscode/settings.json:Zone.Identifier
vendored
Normal file
30
sheet5/3/Makefile
Normal file
30
sheet5/3/Makefile
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#
|
||||||
|
# use GNU-Compiler tools
|
||||||
|
COMPILER=GCC_
|
||||||
|
# alternatively from the shell
|
||||||
|
# export COMPILER=GCC_
|
||||||
|
# or, alternatively from the shell
|
||||||
|
# make COMPILER=GCC_
|
||||||
|
|
||||||
|
# use Intel compilers
|
||||||
|
#COMPILER=ICC_
|
||||||
|
|
||||||
|
# use PGI compilers
|
||||||
|
# COMPILER=PGI_
|
||||||
|
|
||||||
|
|
||||||
|
SOURCES = main.cpp
|
||||||
|
OBJECTS = $(SOURCES:.cpp=.o)
|
||||||
|
|
||||||
|
PROGRAM = main.${COMPILER}
|
||||||
|
|
||||||
|
# uncomment the next to lines for debugging and detailed performance analysis
|
||||||
|
CXXFLAGS += -g
|
||||||
|
LINKFLAGS += -g
|
||||||
|
# do not use -pg with PGI compilers
|
||||||
|
|
||||||
|
ifndef COMPILER
|
||||||
|
COMPILER=GCC_
|
||||||
|
endif
|
||||||
|
|
||||||
|
include ../${COMPILER}default.mk
|
||||||
0
sheet5/3/Makefile:Zone.Identifier
Normal file
0
sheet5/3/Makefile:Zone.Identifier
Normal file
0
sheet5/3/Makefile:Zone.Identifier:Zone.Identifier
Normal file
0
sheet5/3/Makefile:Zone.Identifier:Zone.Identifier
Normal file
BIN
sheet5/3/main.GCC_
Executable file
BIN
sheet5/3/main.GCC_
Executable file
Binary file not shown.
77
sheet5/3/main.cpp
Normal file
77
sheet5/3/main.cpp
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include "mayer_primes.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "timing.h"
|
||||||
|
#include "omp.h"
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
vector<unsigned int> count_goldbach(unsigned int n)
|
||||||
|
{
|
||||||
|
vector<unsigned int> primes = get_primes(n);
|
||||||
|
size_t npr = primes.size();
|
||||||
|
int nthreads = omp_get_max_threads();
|
||||||
|
|
||||||
|
vector<vector<unsigned int>> local_counts(nthreads, vector<unsigned int>(n+1, 0));
|
||||||
|
|
||||||
|
#pragma omp parallel
|
||||||
|
{
|
||||||
|
int tid = omp_get_thread_num();
|
||||||
|
auto &lc = local_counts[tid];
|
||||||
|
|
||||||
|
#pragma omp for schedule(static)
|
||||||
|
for (int j = 0; j < (int)npr; ++j)
|
||||||
|
{
|
||||||
|
unsigned int p = primes[j];
|
||||||
|
for (unsigned int i = j;i < primes.size() && p + primes[i] <= n; ++i)
|
||||||
|
{
|
||||||
|
unsigned int q = primes[i];
|
||||||
|
unsigned int s = p + q;
|
||||||
|
|
||||||
|
lc[s] +=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// combine
|
||||||
|
vector<unsigned int> counts(n+1, 0);
|
||||||
|
for (int t = 0; t < nthreads; ++t)
|
||||||
|
for (unsigned int k = 0; k <= n; ++k)
|
||||||
|
counts[k] += local_counts[t][k];
|
||||||
|
|
||||||
|
return counts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//3
|
||||||
|
vector<unsigned int> counts = count_goldbach(100000);
|
||||||
|
cout << (max_element(counts.begin(), counts.end()) - counts.begin()) << endl;
|
||||||
|
|
||||||
|
//4
|
||||||
|
vector<unsigned int> nvalues = {10000, 100000, 400000, 1000000, 2000000};
|
||||||
|
double time;
|
||||||
|
unsigned int n;
|
||||||
|
for(unsigned int i = 0; i< nvalues.size(); i++)
|
||||||
|
{
|
||||||
|
n = nvalues.at(i);
|
||||||
|
tic();
|
||||||
|
count_goldbach(n);
|
||||||
|
time = toc();
|
||||||
|
cout << "Time for n=" << n << ": " << time << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
0
sheet5/3/main.cpp:Zone.Identifier
Normal file
0
sheet5/3/main.cpp:Zone.Identifier
Normal file
BIN
sheet5/3/main.o
Normal file
BIN
sheet5/3/main.o
Normal file
Binary file not shown.
73
sheet5/3/mayer_primes.h
Normal file
73
sheet5/3/mayer_primes.h
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstring> //memset
|
||||||
|
#include <vector>
|
||||||
|
//using namespace std;
|
||||||
|
|
||||||
|
/** \brief Determines all prime numbers in interval [2, @p max].
|
||||||
|
*
|
||||||
|
* The sieve of Eratosthenes is used.
|
||||||
|
*
|
||||||
|
* The implementation originates from <a href="http://code.activestate.com/recipes/576559-fast-prime-generator/">Florian Mayer</a>.
|
||||||
|
*
|
||||||
|
* \param[in] max end of interval for the prime number search.
|
||||||
|
* \return vector of prime numbers @f$2,3,5, ..., p<=max @f$.
|
||||||
|
*
|
||||||
|
* \copyright
|
||||||
|
* Copyright (c) 2008 Florian Mayer (adapted by Gundolf Haase 2018)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
std::vector<T> get_primes(T max)
|
||||||
|
{
|
||||||
|
std::vector<T> primes;
|
||||||
|
char *sieve;
|
||||||
|
sieve = new char[max / 8 + 1];
|
||||||
|
// Fill sieve with 1
|
||||||
|
memset(sieve, 0xFF, (max / 8 + 1) * sizeof(char));
|
||||||
|
for (T x = 2; x <= max; x++)
|
||||||
|
{
|
||||||
|
if (sieve[x / 8] & (0x01 << (x % 8))) {
|
||||||
|
primes.push_back(x);
|
||||||
|
// Is prime. Mark multiplicates.
|
||||||
|
for (T j = 2 * x; j <= max; j += x)
|
||||||
|
{
|
||||||
|
sieve[j / 8] &= ~(0x01 << (j % 8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] sieve;
|
||||||
|
return primes;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
//int main() // by Florian Mayer
|
||||||
|
//{g++ -O3 -std=c++14 -fopenmp main.cpp && ./a.out
|
||||||
|
// vector<unsigned long> primes;
|
||||||
|
// primes = get_primes(10000000);
|
||||||
|
// // return 0;
|
||||||
|
// // Print out result.
|
||||||
|
// vector<unsigned long>::iterator it;
|
||||||
|
// for(it=primes.begin(); it < primes.end(); it++)
|
||||||
|
// cout << *it << " ";
|
||||||
|
//
|
||||||
|
// cout << endl;
|
||||||
|
// return 0;
|
||||||
|
//}
|
||||||
3
sheet5/3/mayer_primes.h:Zone.Identifier
Normal file
3
sheet5/3/mayer_primes.h:Zone.Identifier
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
[ZoneTransfer]
|
||||||
|
ZoneId=3
|
||||||
|
HostUrl=https://imsc.uni-graz.at/haasegu/Lectures/Math2CPP/Examples/goldbach/mayer_primes.h
|
||||||
0
sheet5/3/mayer_primes.h:Zone.Identifier:Zone.Identifier
Normal file
0
sheet5/3/mayer_primes.h:Zone.Identifier:Zone.Identifier
Normal file
51
sheet5/3/timing.h
Normal file
51
sheet5/3/timing.h
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
//
|
||||||
|
// Gundolf Haase, Oct 18 2024
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
#include <chrono> // timing
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
|
//using Clock = std::chrono::system_clock; //!< The wall clock timer chosen
|
||||||
|
using Clock = std::chrono::high_resolution_clock;
|
||||||
|
using TPoint= std::chrono::time_point<Clock>;
|
||||||
|
|
||||||
|
// [Galowicz, C++17 STL Cookbook, p. 29]
|
||||||
|
|
||||||
|
std::stack<TPoint> MyStopWatch; //!< starting time of stopwatch
|
||||||
|
|
||||||
|
/** Starts stopwatch timer.
|
||||||
|
* Use as @code tic(); myfunction(...) ; double tsec = toc(); @endcode
|
||||||
|
*
|
||||||
|
* The timining can be nested and the recent time point is stored on top of the stack.
|
||||||
|
*
|
||||||
|
* @return recent time point
|
||||||
|
* @see toc
|
||||||
|
*/
|
||||||
|
auto tic()
|
||||||
|
{
|
||||||
|
MyStopWatch.push(Clock::now());
|
||||||
|
return MyStopWatch.top();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the elapsed time from stopwatch.
|
||||||
|
*
|
||||||
|
* The time point from top of the stack is used
|
||||||
|
* if time point @p t_b is not passed as input parameter.
|
||||||
|
* Use as @code tic(); myfunction(...) ; double tsec = toc(); @endcode
|
||||||
|
* or as @code auto t_b = tic(); myfunction(...) ; double tsec = toc(t_b); @endcode
|
||||||
|
* The last option is to be used in the case of
|
||||||
|
* non-nested but overlapping time measurements.
|
||||||
|
*
|
||||||
|
* @param[in] t_b start time of some stop watch
|
||||||
|
* @return elapsed time in seconds.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
double toc(TPoint const &t_b = MyStopWatch.top())
|
||||||
|
{
|
||||||
|
// https://en.cppreference.com/w/cpp/chrono/treat_as_floating_point
|
||||||
|
using Unit = std::chrono::seconds;
|
||||||
|
using FpSeconds = std::chrono::duration<double, Unit::period>;
|
||||||
|
auto t_e = Clock::now();
|
||||||
|
MyStopWatch.pop();
|
||||||
|
return FpSeconds(t_e-t_b).count();
|
||||||
|
}
|
||||||
0
sheet5/3/timing.h:Zone.Identifier
Normal file
0
sheet5/3/timing.h:Zone.Identifier
Normal file
0
sheet5/3/timing.h:Zone.Identifier:Zone.Identifier
Normal file
0
sheet5/3/timing.h:Zone.Identifier:Zone.Identifier
Normal file
6
sheet5/4/.vscode/settings.json
vendored
Normal file
6
sheet5/4/.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"ostream": "cpp",
|
||||||
|
"iostream": "cpp"
|
||||||
|
}
|
||||||
|
}
|
||||||
0
sheet5/4/.vscode/settings.json:Zone.Identifier
vendored
Normal file
0
sheet5/4/.vscode/settings.json:Zone.Identifier
vendored
Normal file
2563
sheet5/4/Doxyfile
Normal file
2563
sheet5/4/Doxyfile
Normal file
File diff suppressed because it is too large
Load diff
0
sheet5/4/Doxyfile:Zone.Identifier
Normal file
0
sheet5/4/Doxyfile:Zone.Identifier
Normal file
30
sheet5/4/Makefile
Normal file
30
sheet5/4/Makefile
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#
|
||||||
|
# use GNU-Compiler tools
|
||||||
|
COMPILER=GCC_
|
||||||
|
# alternatively from the shell
|
||||||
|
# export COMPILER=GCC_
|
||||||
|
# or, alternatively from the shell
|
||||||
|
# make COMPILER=GCC_
|
||||||
|
|
||||||
|
# use Intel compilers
|
||||||
|
#COMPILER=ICC_
|
||||||
|
|
||||||
|
# use PGI compilers
|
||||||
|
# COMPILER=PGI_
|
||||||
|
|
||||||
|
|
||||||
|
SOURCES = main.cpp mylib.cpp benchmark.cpp
|
||||||
|
OBJECTS = $(SOURCES:.cpp=.o)
|
||||||
|
|
||||||
|
PROGRAM = main.${COMPILER}
|
||||||
|
|
||||||
|
# uncomment the next to lines for debugging and detailed performance analysis
|
||||||
|
CXXFLAGS += -g
|
||||||
|
LINKFLAGS += -g
|
||||||
|
# do not use -pg with PGI compilers
|
||||||
|
|
||||||
|
ifndef COMPILER
|
||||||
|
COMPILER=GCC_
|
||||||
|
endif
|
||||||
|
|
||||||
|
include ../${COMPILER}default.mk
|
||||||
0
sheet5/4/Makefile:Zone.Identifier
Normal file
0
sheet5/4/Makefile:Zone.Identifier
Normal file
BIN
sheet5/4/bench
Executable file
BIN
sheet5/4/bench
Executable file
Binary file not shown.
115
sheet5/4/benchmark.cpp
Normal file
115
sheet5/4/benchmark.cpp
Normal file
|
|
@ -0,0 +1,115 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <cmath>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
// Inner product
|
||||||
|
double benchmark_A(const vector<double> &x, const vector<double> &y)
|
||||||
|
{
|
||||||
|
double sum = 0.0;
|
||||||
|
#pragma omp parallel for reduction(+:sum)
|
||||||
|
for (unsigned int i = 0; i < x.size(); i++)
|
||||||
|
{
|
||||||
|
sum += x[i]*y[i];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inner product
|
||||||
|
double benchmark_A_sum(const vector<double> &x)
|
||||||
|
{
|
||||||
|
double sum = 0.0;
|
||||||
|
#pragma omp parallel for reduction(+:sum)
|
||||||
|
for (unsigned int i = 0; i < x.size(); i++)
|
||||||
|
{
|
||||||
|
sum += x[i];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Matrix-vector product
|
||||||
|
vector<double> benchmark_B(const vector<double> &A, const vector<double> &x)
|
||||||
|
{
|
||||||
|
unsigned int N = x.size();
|
||||||
|
unsigned int M = A.size() / N;
|
||||||
|
vector<double> b(M, 0.0);
|
||||||
|
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (unsigned int i = 0; i < M; i++)
|
||||||
|
{
|
||||||
|
double bi = 0.0;
|
||||||
|
for (unsigned int j = 0; j < N; j++)
|
||||||
|
{
|
||||||
|
bi += A[i*N+j]*x[j];
|
||||||
|
}
|
||||||
|
b[i] = bi;
|
||||||
|
}
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Matrix-Matrix product
|
||||||
|
vector<double> benchmark_C(const vector<double> &A, const vector<double> &B, unsigned int M)
|
||||||
|
{
|
||||||
|
unsigned int L = A.size()/M;
|
||||||
|
unsigned int N = B.size()/L;
|
||||||
|
vector<double> C(M*N,0.0);
|
||||||
|
#pragma omp parallel for collapse(2)
|
||||||
|
for (unsigned int i = 0; i < M; i++)
|
||||||
|
{
|
||||||
|
for (unsigned int j = 0; j < N; j++)
|
||||||
|
{
|
||||||
|
double sum = 0.0;
|
||||||
|
for (unsigned int k = 0; k < L; k++)
|
||||||
|
{
|
||||||
|
sum += A[i*L+k]*B[k*N+j];
|
||||||
|
}
|
||||||
|
C[i*N+j] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return C;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//polynomial evaluation
|
||||||
|
vector<double> benchmark_D(const vector<double>& coeff, const vector<double>& x)
|
||||||
|
{
|
||||||
|
unsigned int p = coeff.size(); // p coefficients, degree p-1
|
||||||
|
unsigned int N = x.size();
|
||||||
|
vector<double> y(N);
|
||||||
|
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (unsigned int i = 0; i < N; i++){
|
||||||
|
double yi = coeff[p-1];
|
||||||
|
double xi = x[i];
|
||||||
|
for(int j=p-2; j>=0; --j)
|
||||||
|
{
|
||||||
|
yi = yi*xi+coeff[j];
|
||||||
|
}
|
||||||
|
y[i] = yi;
|
||||||
|
}
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double benchmark_A_old(const vector<double> &x, const vector<double> &y)
|
||||||
|
{
|
||||||
|
double sum = 0.0;
|
||||||
|
for (unsigned int i = 0; i < x.size(); i++)
|
||||||
|
{
|
||||||
|
sum += x[i]*y[i];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
double benchmark_A_sum_old(const vector<double> &x)
|
||||||
|
{
|
||||||
|
double sum = 0.0;
|
||||||
|
for (unsigned int i = 0; i < x.size(); i++)
|
||||||
|
{
|
||||||
|
sum += x[i];
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
0
sheet5/4/benchmark.cpp:Zone.Identifier
Normal file
0
sheet5/4/benchmark.cpp:Zone.Identifier
Normal file
27
sheet5/4/benchmark.h
Normal file
27
sheet5/4/benchmark.h
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef BENCHMARK_H
|
||||||
|
#define BENCHMARK_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
double benchmark_A(const vector<double> &x,
|
||||||
|
const vector<double> &y);
|
||||||
|
double benchmark_A_sum(const vector<double> &x);
|
||||||
|
|
||||||
|
vector<double> benchmark_B(const vector<double> &A,
|
||||||
|
const vector<double> &x);
|
||||||
|
|
||||||
|
vector<double> benchmark_C(const vector<double> &A,
|
||||||
|
const vector<double> &B,
|
||||||
|
unsigned int M);
|
||||||
|
|
||||||
|
vector<double> benchmark_D(const vector<double> &coefficients,
|
||||||
|
const vector<double> &x);
|
||||||
|
double benchmark_A_old(const vector<double> &x,
|
||||||
|
const vector<double> &y);
|
||||||
|
double benchmark_A_sum_old(const vector<double> &x);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
0
sheet5/4/benchmark.h:Zone.Identifier
Normal file
0
sheet5/4/benchmark.h:Zone.Identifier
Normal file
BIN
sheet5/4/benchmark.o
Normal file
BIN
sheet5/4/benchmark.o
Normal file
Binary file not shown.
BIN
sheet5/4/main.GCC_
Executable file
BIN
sheet5/4/main.GCC_
Executable file
Binary file not shown.
234
sheet5/4/main.cpp
Normal file
234
sheet5/4/main.cpp
Normal file
|
|
@ -0,0 +1,234 @@
|
||||||
|
#include "mylib.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <chrono> // timing
|
||||||
|
#include <cmath> // sqrt()
|
||||||
|
#include <cstdlib> // atoi()
|
||||||
|
#include <cstring> // strncmp()
|
||||||
|
#include <ctime>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include "benchmark.h"
|
||||||
|
#include "omp.h"
|
||||||
|
using namespace std;
|
||||||
|
using namespace std::chrono; // timing
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
const unsigned int NA = 1400000;
|
||||||
|
const unsigned int NLOOPSA = 2000;
|
||||||
|
//const unsigned int NLOOPS = 10;
|
||||||
|
|
||||||
|
const unsigned int MC = 1000;
|
||||||
|
int const NLOOPSC = 5;
|
||||||
|
// ---------- Benchmark A ----------
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
vector<double> xA(NA), yA(NA);
|
||||||
|
for (unsigned int i = 0; i < NA; ++i)
|
||||||
|
{
|
||||||
|
double xi= (i % 219) + 1;
|
||||||
|
xA[i] = xi;
|
||||||
|
yA[i] = 1.0 / xi;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto tA1 = system_clock::now();
|
||||||
|
double sA = 0.0, sumA = 0.0;
|
||||||
|
for (unsigned int loop = 0; loop < NLOOPSA; ++loop)
|
||||||
|
{
|
||||||
|
sA = benchmark_A(xA, yA);
|
||||||
|
sumA += sA;
|
||||||
|
}
|
||||||
|
auto tA2 = system_clock::now();
|
||||||
|
|
||||||
|
auto durA = duration_cast<microseconds>(tA2 - tA1);
|
||||||
|
double tA = static_cast<double>(durA.count()) / 1e6 / NLOOPSA; //duration per loop seconds
|
||||||
|
|
||||||
|
cout << "\n===== Benchmark A =====\n";
|
||||||
|
cout << "<xA,yA> = " << sA << endl;
|
||||||
|
cout << "Timing in sec. : " << tA << endl;
|
||||||
|
cout << "GFLOPS : " << 2.0 * NA / tA / 1024 / 1024 / 1024 << endl;
|
||||||
|
cout << "GiByte/s : "
|
||||||
|
<< 2.0 * NA * sizeof(xA[0]) / tA / 1024 / 1024 / 1024 << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Benchmark B----------
|
||||||
|
|
||||||
|
{
|
||||||
|
const unsigned int MB = 1700;
|
||||||
|
const unsigned int NB = MB;
|
||||||
|
const unsigned int NLOOPSB = 200;//50;
|
||||||
|
|
||||||
|
vector<double> AB(MB * NB);
|
||||||
|
vector<double> xB(NB);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < MB; ++i)
|
||||||
|
for (unsigned int j = 0; j < NB; ++j)
|
||||||
|
AB[i * NB + j] = (i+j) %219 +1;
|
||||||
|
|
||||||
|
for (unsigned int j = 0; j < NB; ++j)
|
||||||
|
{
|
||||||
|
|
||||||
|
xB[j] = 1.0 / AB[17*NB+j];
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<double> bB;
|
||||||
|
auto tB1 = system_clock::now();
|
||||||
|
double guardB = 0.0;
|
||||||
|
for (unsigned int loop = 0; loop < NLOOPSB; ++loop)
|
||||||
|
{
|
||||||
|
bB = benchmark_B(AB, xB);
|
||||||
|
guardB += bB[17];
|
||||||
|
}
|
||||||
|
auto tB2 = system_clock::now();
|
||||||
|
|
||||||
|
auto durB = duration_cast<microseconds>(tB2 - tB1);
|
||||||
|
double tB = static_cast<double>(durB.count()) / 1e6 / NLOOPSB;
|
||||||
|
|
||||||
|
double flopsB = 2.0 * MB * NB;
|
||||||
|
double bytesB = (MB * NB + NB + MB) * sizeof(double);
|
||||||
|
|
||||||
|
cout << "\n===== Benchmark B =====\n";
|
||||||
|
cout << guardB << endl;
|
||||||
|
cout << "bytes: " << bytesB << endl;
|
||||||
|
cout << "Timing in sec. : " << tB << endl;
|
||||||
|
cout << "GFLOPS : " << flopsB / tB / 1024 / 1024 / 1024 << endl;
|
||||||
|
cout << "GiByte/s : " << bytesB / tB / 1024 / 1024 / 1024 << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Benchmark C ----------
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
const unsigned int LC = MC;
|
||||||
|
const unsigned int NC = MC;
|
||||||
|
|
||||||
|
|
||||||
|
vector<double> AC(MC * LC), BC(LC * NC);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < MC; ++i)
|
||||||
|
for (unsigned int j = 0; j < LC; ++j)
|
||||||
|
AC[i * LC + j] = (i+j) %219 +1;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < LC; ++i)
|
||||||
|
for (unsigned int j = 0; j < NC; ++j)
|
||||||
|
BC[i * NC + j] = (i+j) %219 +1;
|
||||||
|
|
||||||
|
vector<double> CC;
|
||||||
|
auto tC1 = system_clock::now();
|
||||||
|
double guardC = 0.0;
|
||||||
|
for (unsigned int loop = 0; loop < NLOOPSC; ++loop)
|
||||||
|
{
|
||||||
|
CC = benchmark_C(AC, BC, MC);
|
||||||
|
guardC += CC[0];
|
||||||
|
}
|
||||||
|
auto tC2 = system_clock::now();
|
||||||
|
|
||||||
|
auto durC = duration_cast<microseconds>(tC2 - tC1);
|
||||||
|
double tC = static_cast<double>(durC.count()) / 1e6 / NLOOPSC;
|
||||||
|
|
||||||
|
double flopsC = 2.0 * MC * LC * NC;
|
||||||
|
double bytesC = (MC * LC + LC * NC + MC * NC)* sizeof(double);
|
||||||
|
|
||||||
|
cout << "\n===== Benchmark C =====\n";
|
||||||
|
cout << guardC << endl;
|
||||||
|
cout << "bytes: " << bytesC << endl;
|
||||||
|
cout << "Timing in sec. : " << tC << endl;
|
||||||
|
cout << "GFLOPS : " << flopsC / tC / 1024 / 1024 / 1024 << endl;
|
||||||
|
cout << "GiByte/s : " << bytesC / tC / 1024 / 1024 / 1024 << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Benchmark D----------
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
const unsigned int ND = 2000000;
|
||||||
|
const unsigned int p = 14; // degree p-1 = 15
|
||||||
|
const unsigned int NLOOPSD = 100;
|
||||||
|
vector<double> coeff(p, 0.0);
|
||||||
|
vector<double> xD(ND);
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < p; ++k)
|
||||||
|
coeff[k] = k%219+1;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < ND; ++i)
|
||||||
|
xD[i] = i%219+1;
|
||||||
|
|
||||||
|
vector<double> yD;
|
||||||
|
auto tD1 = system_clock::now();
|
||||||
|
double guardD = 0.0;
|
||||||
|
for (unsigned int loop = 0; loop < NLOOPSD; ++loop)
|
||||||
|
{
|
||||||
|
|
||||||
|
yD = benchmark_D(coeff, xD);
|
||||||
|
guardD += yD[0];
|
||||||
|
}
|
||||||
|
auto tD2 = system_clock::now();
|
||||||
|
|
||||||
|
auto durD = duration_cast<microseconds>(tD2 - tD1);
|
||||||
|
double tD = static_cast<double>(durD.count()) / 1e6 / NLOOPSD;
|
||||||
|
|
||||||
|
|
||||||
|
double flopsD = ND * 2 * p;
|
||||||
|
double bytesD = (p + 2 * ND)*sizeof(double);
|
||||||
|
|
||||||
|
cout << "\n===== Benchmark D =====\n";
|
||||||
|
cout << guardD << endl;
|
||||||
|
cout << "bytes: " << bytesD << endl;
|
||||||
|
cout << "Timing in sec. : " << tD << endl;
|
||||||
|
cout << "GFLOPS : " << flopsD / tD / 1024 / 1024 / 1024 << endl;
|
||||||
|
cout << "GiByte/s : " << bytesD / tD / 1024 / 1024 / 1024 << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (int k = 3; k <= 8; ++k)
|
||||||
|
{
|
||||||
|
size_t n = (size_t)pow(10, k);
|
||||||
|
|
||||||
|
vector<double> x(n), y(n);
|
||||||
|
for (unsigned int i = 0; i < n; ++i)
|
||||||
|
{
|
||||||
|
double xi= (i % 219) + 1;
|
||||||
|
x[i] = xi;
|
||||||
|
y[i] = 1.0 / xi;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- SUM benchmark (sequential) ----
|
||||||
|
double t0 = omp_get_wtime();
|
||||||
|
double s1 = benchmark_A_sum_old(x);
|
||||||
|
double t_sum_seq = omp_get_wtime() - t0;
|
||||||
|
|
||||||
|
// ---- SUM benchmark (parallel) ----
|
||||||
|
t0 = omp_get_wtime();
|
||||||
|
double s2 = benchmark_A_sum(x);
|
||||||
|
double t_sum_omp = omp_get_wtime() - t0;
|
||||||
|
|
||||||
|
double sum_speedup = t_sum_seq / t_sum_omp;
|
||||||
|
|
||||||
|
|
||||||
|
// ---- INNER PRODUCT benchmark (sequential) ----
|
||||||
|
t0 = omp_get_wtime();
|
||||||
|
double ip1 = benchmark_A_old(x, y);
|
||||||
|
double t_inner_seq = omp_get_wtime() - t0;
|
||||||
|
|
||||||
|
// ---- INNER PRODUCT benchmark (parallel) ----
|
||||||
|
t0 = omp_get_wtime();
|
||||||
|
double ip2 = benchmark_A(x, y);
|
||||||
|
double t_inner_omp = omp_get_wtime() - t0;
|
||||||
|
|
||||||
|
double inner_speedup = t_inner_seq / t_inner_omp;
|
||||||
|
|
||||||
|
// ---- Print results ----
|
||||||
|
cout << k << endl;
|
||||||
|
cout << t_sum_seq << ", " << t_sum_omp << ", " << sum_speedup << endl;
|
||||||
|
cout << t_inner_seq << ", " << t_inner_omp << ", " << inner_speedup << endl;
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
0
sheet5/4/main.cpp:Zone.Identifier
Normal file
0
sheet5/4/main.cpp:Zone.Identifier
Normal file
BIN
sheet5/4/main.o
Normal file
BIN
sheet5/4/main.o
Normal file
Binary file not shown.
65
sheet5/4/mylib.cpp
Normal file
65
sheet5/4/mylib.cpp
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
#include "mylib.h"
|
||||||
|
#include <cassert> // assert()
|
||||||
|
#include <cmath>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifdef __INTEL_CLANG_COMPILER
|
||||||
|
#pragma message(" ########## Use of MKL ###############")
|
||||||
|
#include <mkl.h>
|
||||||
|
#else
|
||||||
|
#pragma message(" ########## Use of CBLAS ###############")
|
||||||
|
//extern "C"
|
||||||
|
//{
|
||||||
|
#include <cblas.h> // cBLAS Library
|
||||||
|
#include <lapacke.h> // Lapack
|
||||||
|
//}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
double scalar(vector<double> const &x, vector<double> const &y)
|
||||||
|
{
|
||||||
|
assert(x.size() == y.size()); // switch off via compile flag: -DNDEBUG
|
||||||
|
size_t const N = x.size();
|
||||||
|
double sum = 0.0;
|
||||||
|
for (size_t i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
sum += x[i] * y[i];
|
||||||
|
//sum += exp(x[i])*log(y[i]);
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double scalar_cblas(vector<double> const &x, vector<double> const &y)
|
||||||
|
{
|
||||||
|
int const asize = static_cast<int>(size(x));
|
||||||
|
int const bsize = static_cast<int>(size(y));
|
||||||
|
assert(asize == bsize); // switch off via compile flag: -DNDEBUG
|
||||||
|
return cblas_ddot(asize,x.data(),1,y.data(),1);
|
||||||
|
//assert(x.size() == y.size()); // switch off via compile flag: -DNDEBUG
|
||||||
|
//return cblas_ddot(x.size(),x.data(),1,y.data(),1);
|
||||||
|
}
|
||||||
|
|
||||||
|
float scalar_cblas(vector<float> const &x, vector<float> const &y)
|
||||||
|
{
|
||||||
|
int const asize = static_cast<int>(size(x));
|
||||||
|
int const bsize = static_cast<int>(size(y));
|
||||||
|
assert(asize == bsize); // switch off via compile flag: -DNDEBUG
|
||||||
|
return cblas_sdot(asize,x.data(),1,y.data(),1);
|
||||||
|
//assert(x.size() == y.size()); // switch off via compile flag: -DNDEBUG
|
||||||
|
//return cblas_ddot(x.size(),x.data(),1,y.data(),1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double norm(vector<double> const &x)
|
||||||
|
{
|
||||||
|
size_t const N = x.size();
|
||||||
|
double sum = 0.0;
|
||||||
|
for (size_t i = 0; i < N; ++i)
|
||||||
|
{
|
||||||
|
sum += x[i] * x[i];
|
||||||
|
}
|
||||||
|
return std::sqrt(sum);
|
||||||
|
}
|
||||||
|
|
||||||
0
sheet5/4/mylib.cpp:Zone.Identifier
Normal file
0
sheet5/4/mylib.cpp:Zone.Identifier
Normal file
30
sheet5/4/mylib.h
Normal file
30
sheet5/4/mylib.h
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef FILE_MYLIB
|
||||||
|
#define FILE_MYLIB
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/** Inner product
|
||||||
|
@param[in] x vector
|
||||||
|
@param[in] y vector
|
||||||
|
@return resulting Euclidian inner product <x,y>
|
||||||
|
*/
|
||||||
|
double scalar(std::vector<double> const &x, std::vector<double> const &y);
|
||||||
|
|
||||||
|
/** Inner product using BLAS routines
|
||||||
|
@param[in] x vector
|
||||||
|
@param[in] y vector
|
||||||
|
@return resulting Euclidian inner product <x,y>
|
||||||
|
*/
|
||||||
|
double scalar_cblas(std::vector<double> const &x, std::vector<double> const &y);
|
||||||
|
float scalar_cblas(std::vector<float> const &x, std::vector<float> const &y);
|
||||||
|
|
||||||
|
|
||||||
|
/** L_2 Norm of a vector
|
||||||
|
@param[in] x vector
|
||||||
|
@return resulting Euclidian norm <x,y>
|
||||||
|
*/
|
||||||
|
double norm(std::vector<double> const &x);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
0
sheet5/4/mylib.h:Zone.Identifier
Normal file
0
sheet5/4/mylib.h:Zone.Identifier
Normal file
BIN
sheet5/4/mylib.o
Normal file
BIN
sheet5/4/mylib.o
Normal file
Binary file not shown.
51
sheet5/4/output.txt
Normal file
51
sheet5/4/output.txt
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
g++ -c -g -O0 -funroll-all-loops -std=c++17 -Wall -pedantic -Wextra -Weffc++ -Woverloaded-virtual -Wfloat-equal -Wshadow -Wredundant-decls -Winline -fmax-errors=1 -flto -o main.o main.cpp
|
||||||
|
g++ -c -g -O0 -funroll-all-loops -std=c++17 -Wall -pedantic -Wextra -Weffc++ -Woverloaded-virtual -Wfloat-equal -Wshadow -Wredundant-decls -Winline -fmax-errors=1 -flto -o mylib.o mylib.cpp
|
||||||
|
g++ -c -g -O0 -funroll-all-loops -std=c++17 -Wall -pedantic -Wextra -Weffc++ -Woverloaded-virtual -Wfloat-equal -Wshadow -Wredundant-decls -Winline -fmax-errors=1 -flto -o benchmark.o benchmark.cpp
|
||||||
|
g++ main.o mylib.o benchmark.o -g -O0 -llapack -lblas -flto -o main.GCC_
|
||||||
|
./main.GCC_
|
||||||
|
|
||||||
|
===== Benchmark A =====
|
||||||
|
<xA,yA> = 1.4e+06
|
||||||
|
Timing in sec. : 0.00893637
|
||||||
|
GFLOPS : 0.291808
|
||||||
|
GiByte/s : 2.33446
|
||||||
|
|
||||||
|
===== Benchmark B =====
|
||||||
|
340000
|
||||||
|
bytes: 2.31472e+07
|
||||||
|
Timing in sec. : 0.0133897
|
||||||
|
GFLOPS : 0.402029
|
||||||
|
GiByte/s : 1.61001
|
||||||
|
|
||||||
|
===== Benchmark C =====
|
||||||
|
7.37196e+07
|
||||||
|
bytes: 2.4e+07
|
||||||
|
Timing in sec. : 8.67235
|
||||||
|
GFLOPS : 0.21478
|
||||||
|
GiByte/s : 0.00257736
|
||||||
|
|
||||||
|
===== Benchmark D =====
|
||||||
|
10500
|
||||||
|
bytes: 3.20001e+07
|
||||||
|
Timing in sec. : 0.101087
|
||||||
|
GFLOPS : 0.515935
|
||||||
|
GiByte/s : 0.294821
|
||||||
|
|
||||||
|
===== Benchmark 5A =====
|
||||||
|
NORM = 150114
|
||||||
|
Timing in sec. : 0.00703533
|
||||||
|
GFLOPS : 0.370658
|
||||||
|
GiByte/s : 1.48263
|
||||||
|
|
||||||
|
===== Benchmark 5B =====
|
||||||
|
<xA,yA> = 1.4e+06
|
||||||
|
Timing in sec. : 0.0108377
|
||||||
|
GFLOPS : 0.601533
|
||||||
|
GiByte/s : 1.92491
|
||||||
|
|
||||||
|
===== Benchmark 5C =====
|
||||||
|
7.37196e+07
|
||||||
|
bytes: 2.4e+07
|
||||||
|
Timing in sec. : 15.2407
|
||||||
|
GFLOPS : 0.122215
|
||||||
|
GiByte/s : 0.00146658
|
||||||
0
sheet5/4/output.txt:Zone.Identifier
Normal file
0
sheet5/4/output.txt:Zone.Identifier
Normal file
1826
sheet5/4/small_Doxyfile
Normal file
1826
sheet5/4/small_Doxyfile
Normal file
File diff suppressed because it is too large
Load diff
0
sheet5/4/small_Doxyfile:Zone.Identifier
Normal file
0
sheet5/4/small_Doxyfile:Zone.Identifier
Normal file
2877
sheet5/5/Doxyfile
Normal file
2877
sheet5/5/Doxyfile
Normal file
File diff suppressed because it is too large
Load diff
0
sheet5/5/Doxyfile:Zone.Identifier
Normal file
0
sheet5/5/Doxyfile:Zone.Identifier
Normal file
54
sheet5/5/Makefile
Normal file
54
sheet5/5/Makefile
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
#
|
||||||
|
# use GNU-Compiler tools
|
||||||
|
COMPILER=GCC_
|
||||||
|
# COMPILER=GCC_SEQ_
|
||||||
|
# alternatively from the shell
|
||||||
|
# export COMPILER=GCC_
|
||||||
|
# or, alternatively from the shell
|
||||||
|
# make COMPILER=GCC_
|
||||||
|
|
||||||
|
MAIN = main
|
||||||
|
SOURCES = ${MAIN}.cpp vdop.cpp geom.cpp\
|
||||||
|
getmatrix.cpp jacsolve.cpp userset.cpp
|
||||||
|
# dexx.cpp debugd.cpp skalar.cpp vecaccu.cpp accudiag.cpp
|
||||||
|
|
||||||
|
OBJECTS = $(SOURCES:.cpp=.o)
|
||||||
|
|
||||||
|
PROGRAM = ${MAIN}.${COMPILER}
|
||||||
|
|
||||||
|
# uncomment the next to lines for debugging and detailed performance analysis
|
||||||
|
CXXFLAGS += -g
|
||||||
|
# -pg slows down the code on my laptop when using CLANG_
|
||||||
|
#LINKFLAGS += -pg
|
||||||
|
#CXXFLAGS += -Q --help=optimizers
|
||||||
|
#CXXFLAGS += -fopt-info
|
||||||
|
|
||||||
|
include ../${COMPILER}default.mk
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# additional specific cleaning in this directory
|
||||||
|
clean_all::
|
||||||
|
@rm -f t.dat*
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# special testing
|
||||||
|
# NPROCS = 4
|
||||||
|
#
|
||||||
|
TFILE = t.dat
|
||||||
|
# TTMP = t.tmp
|
||||||
|
#
|
||||||
|
graph: $(PROGRAM)
|
||||||
|
# @rm -f $(TFILE).*
|
||||||
|
# next two lines only sequentially
|
||||||
|
./$(PROGRAM)
|
||||||
|
@mv $(TFILE).000 $(TFILE)
|
||||||
|
# $(MPIRUN) $(MPIFLAGS) -np $(NPROCS) $(PROGRAM)
|
||||||
|
# @echo " "; echo "Manipulate data for graphics."; echo " "
|
||||||
|
# @cat $(TFILE).* > $(TTMP)
|
||||||
|
# @sort -b -k 2 $(TTMP) -o $(TTMP).1
|
||||||
|
# @sort -b -k 1 $(TTMP).1 -o $(TTMP).2
|
||||||
|
# @awk -f nl.awk $(TTMP).2 > $(TFILE)
|
||||||
|
# @rm -f $(TTMP).* $(TTMP) $(TFILE).*
|
||||||
|
#
|
||||||
|
-gnuplot jac.dem
|
||||||
0
sheet5/5/Makefile:Zone.Identifier
Normal file
0
sheet5/5/Makefile:Zone.Identifier
Normal file
5
sheet5/5/ToDo.txt
Normal file
5
sheet5/5/ToDo.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
// Jan 15, 2019
|
||||||
|
|
||||||
|
geom.h:75 void SetValues(std::vector<double> &v) const; // GH: TODO with functor
|
||||||
|
Set vector values using a functor ff(x,y).
|
||||||
|
See solution in Progs/cds
|
||||||
0
sheet5/5/ToDo.txt:Zone.Identifier
Normal file
0
sheet5/5/ToDo.txt:Zone.Identifier
Normal file
43
sheet5/5/ascii_read_meshvector.m
Normal file
43
sheet5/5/ascii_read_meshvector.m
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
function [ xc, ia, v ] = ascii_read_meshvector( fname )
|
||||||
|
%
|
||||||
|
% Loads the 2D triangular mesh (coordinates, vertex connectivity)
|
||||||
|
% together with values on its vertices from an ASCII file.
|
||||||
|
% Matlab indexing is stored (starts with 1).
|
||||||
|
%
|
||||||
|
% The input file format is compatible
|
||||||
|
% with Mesh_2d_3_matlab:Write_ascii_matlab(..) in jacobi_oo_stl/geom.h
|
||||||
|
%
|
||||||
|
%
|
||||||
|
% IN: fname - filename
|
||||||
|
% OUT: xc - coordinates
|
||||||
|
% ia - mesh connectivity
|
||||||
|
% v - solution vector
|
||||||
|
|
||||||
|
DELIMETER = ' ';
|
||||||
|
|
||||||
|
fprintf('Read file %s\n',fname)
|
||||||
|
|
||||||
|
% Read mesh constants
|
||||||
|
nn = dlmread(fname,DELIMETER,[0 0 0 3]); %% row_1, col_1, row_2, col_2 in C indexing!!!
|
||||||
|
nnode = nn(1);
|
||||||
|
ndim = nn(2);
|
||||||
|
nelem = nn(3);
|
||||||
|
nvert = nn(4);
|
||||||
|
|
||||||
|
% Read coordinates
|
||||||
|
row_start = 0+1;
|
||||||
|
row_end = 0+nnode;
|
||||||
|
xc = dlmread(fname,DELIMETER,[row_start 0 row_end ndim-1]);
|
||||||
|
|
||||||
|
% Read connectivity
|
||||||
|
row_start = row_end+1;
|
||||||
|
row_end = row_end+nelem;
|
||||||
|
ia = dlmread(fname,DELIMETER,[row_start 0 row_end nvert-1]);
|
||||||
|
|
||||||
|
% Read solution
|
||||||
|
row_start = row_end+1;
|
||||||
|
row_end = row_end+nnode;
|
||||||
|
v = dlmread(fname,DELIMETER,[row_start 0 row_end 0]);
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
0
sheet5/5/ascii_read_meshvector.m:Zone.Identifier
Normal file
0
sheet5/5/ascii_read_meshvector.m:Zone.Identifier
Normal file
49
sheet5/5/ascii_write_mesh.m
Normal file
49
sheet5/5/ascii_write_mesh.m
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
function ascii_write_mesh( xc, ia, e, basename)
|
||||||
|
%
|
||||||
|
% Saves the 2D triangular mesh in the minimal way (only coordinates, vertex connectivity, minimal boundary edge info)
|
||||||
|
% in an ASCII file.
|
||||||
|
% Matlab indexing is stored (starts with 1).
|
||||||
|
%
|
||||||
|
% The output file format is compatible with Mesh_2d_3_matlab:Mesh_2d_3_matlab(std::string const &fname) in jacobi_oo_stl/geom.h
|
||||||
|
%
|
||||||
|
% IN:
|
||||||
|
% coordinates xc: [2][nnode]
|
||||||
|
% connectivity ia: [4][nelem] with t(4,:) are the subdomain numbers
|
||||||
|
% edges e: [7][nedges] boundary edges
|
||||||
|
% e([1,2],:) - start/end vertex of edge
|
||||||
|
% e([3,4],:) - start/end values
|
||||||
|
% e(5,:) - segment number
|
||||||
|
% e([6,7],:) - left/right subdomain
|
||||||
|
% basename: file name without extension
|
||||||
|
%
|
||||||
|
% Data have been generated via <https://de.mathworks.com/help/pde/ug/initmesh.html initmesh>.
|
||||||
|
%
|
||||||
|
fname = [basename, '.txt'];
|
||||||
|
|
||||||
|
nnode = int32(size(xc,2));
|
||||||
|
ndim = int32(size(xc,1));
|
||||||
|
nelem = int32(size(ia,2));
|
||||||
|
nvert_e = int32(3);
|
||||||
|
|
||||||
|
|
||||||
|
dlmwrite(fname,nnode,'delimiter','\t','precision',16) % number of nodes
|
||||||
|
dlmwrite(fname,ndim,'-append','delimiter','\t','precision',16) % space dimension
|
||||||
|
dlmwrite(fname,nelem,'-append','delimiter','\t','precision',16) % number of elements
|
||||||
|
dlmwrite(fname,nvert_e,'-append','delimiter','\t','precision',16) % number of vertices per element
|
||||||
|
|
||||||
|
% dlmwrite(fname,xc(:),'-append','delimiter','\t','precision',16) % coordinates
|
||||||
|
dlmwrite(fname,xc([1,2],:).','-append','delimiter','\t','precision',16) % coordinates
|
||||||
|
|
||||||
|
% no subdomain info transferred
|
||||||
|
tmp=int32(ia(1:3,:));
|
||||||
|
% dlmwrite(fname,tmp(:),'-append','delimiter','\t','precision',16) % connectivity in Matlab indexing
|
||||||
|
dlmwrite(fname,tmp(:,:).','-append','delimiter','\t','precision',16) % connectivity in Matlab indexing
|
||||||
|
|
||||||
|
% store only start and end point of boundary edges,
|
||||||
|
nbedges = size(e,2);
|
||||||
|
dlmwrite(fname,nbedges,'-append','delimiter','\t','precision',16) % number boundary edges
|
||||||
|
tmp=int32(e(1:2,:));
|
||||||
|
% dlmwrite(fname,tmp(:),'-append','delimiter','\t','precision',16) % boundary edges in Matlab indexing
|
||||||
|
dlmwrite(fname,tmp(:,:).','-append','delimiter','\t','precision',16) % boundary edges in Matlab indexing
|
||||||
|
|
||||||
|
end
|
||||||
0
sheet5/5/ascii_write_mesh.m:Zone.Identifier
Normal file
0
sheet5/5/ascii_write_mesh.m:Zone.Identifier
Normal file
522
sheet5/5/geom.cpp
Normal file
522
sheet5/5/geom.cpp
Normal file
|
|
@ -0,0 +1,522 @@
|
||||||
|
// see: http://llvm.org/docs/CodingStandards.html#include-style
|
||||||
|
#include "geom.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
Mesh::Mesh(int ndim, int nvert_e, int ndof_e)
|
||||||
|
: _nelem(0), _nvert_e(nvert_e), _ndof_e(ndof_e), _nnode(0), _ndim(ndim), _ia(0), _xc(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh::~Mesh()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Mesh::SetValues(std::vector<double> &v, const std::function<double(double, double)> &func) const
|
||||||
|
{
|
||||||
|
int const nnode = Nnodes(); // number of vertices in mesh
|
||||||
|
assert( nnode == static_cast<int>(v.size()) );
|
||||||
|
for (int k = 0; k < nnode; ++k)
|
||||||
|
{
|
||||||
|
v[k] = func( _xc[2 * k], _xc[2 * k + 1] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Mesh::Debug() const
|
||||||
|
{
|
||||||
|
cout << "\n ############### Debug M E S H ###################\n";
|
||||||
|
cout << "\n ............... Coordinates ...................\n";
|
||||||
|
for (int k = 0; k < _nnode; ++k)
|
||||||
|
{
|
||||||
|
cout << k << " : " ;
|
||||||
|
for (int i = 0; i < _ndof_e; ++i )
|
||||||
|
{
|
||||||
|
cout << _xc[2*k+i] << " ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
cout << "\n ............... Elements ...................\n";
|
||||||
|
for (int k = 0; k < _nelem; ++k)
|
||||||
|
{
|
||||||
|
cout << k << " : ";
|
||||||
|
for (int i = 0; i < _ndof_e; ++i )
|
||||||
|
cout << _ia[_ndof_e * k + i] << " ";
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::Write_ascii_matlab(std::string const &fname, std::vector<double> const &v) const
|
||||||
|
{
|
||||||
|
assert(Nnodes() == static_cast<int>(v.size())); // fits vector length to mesh information?
|
||||||
|
|
||||||
|
ofstream fout(fname); // open file ASCII mode
|
||||||
|
if ( !fout.is_open() )
|
||||||
|
{
|
||||||
|
cout << "\nFile " << fname << " has not been opened.\n\n" ;
|
||||||
|
assert( fout.is_open() && "File not opened." );
|
||||||
|
}
|
||||||
|
|
||||||
|
string const DELIMETER(" "); // define the same delimeter as in matlab/ascii_read*.m
|
||||||
|
int const OFFSET(1); // convert C-indexing to matlab
|
||||||
|
|
||||||
|
// Write data: #nodes, #space dimensions, #elements, #vertices per element
|
||||||
|
fout << Nnodes() << DELIMETER << Ndims() << DELIMETER << Nelems() << DELIMETER << NverticesElements() << endl;
|
||||||
|
|
||||||
|
// Write cordinates: x_k, y_k in seperate lines
|
||||||
|
assert( Nnodes()*Ndims() == static_cast<int>(_xc.size()));
|
||||||
|
for (int k = 0, kj = 0; k < Nnodes(); ++k)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < Ndims(); ++j, ++kj)
|
||||||
|
{
|
||||||
|
fout << _xc[kj] << DELIMETER;
|
||||||
|
}
|
||||||
|
fout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write connectivity: ia_k,0, ia_k,1 etc in seperate lines
|
||||||
|
assert( Nelems()*NverticesElements() == static_cast<int>(_ia.size()));
|
||||||
|
for (int k = 0, kj = 0; k < Nelems(); ++k)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < NverticesElements(); ++j, ++kj)
|
||||||
|
{
|
||||||
|
fout << _ia[kj] + OFFSET << DELIMETER; // C to matlab
|
||||||
|
}
|
||||||
|
fout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write vector
|
||||||
|
for (int k = 0; k < Nnodes(); ++k)
|
||||||
|
{
|
||||||
|
fout << v[k] << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
fout.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Mesh::Visualize(std::vector<double> const &v) const
|
||||||
|
{
|
||||||
|
// define external command
|
||||||
|
const string exec_m("matlab -nosplash < visualize_results.m"); // Matlab
|
||||||
|
//const string exec_m("octave --no-window-system --no-gui visualize_results.m"); // Octave
|
||||||
|
//const string exec_m("flatpak run org.octave.Octave visualize_results.m"); // Octave (flatpak): desktop GH
|
||||||
|
|
||||||
|
const string fname("uv.txt");
|
||||||
|
Write_ascii_matlab(fname, v);
|
||||||
|
|
||||||
|
int ierror = system(exec_m.c_str()); // call external command
|
||||||
|
|
||||||
|
if (ierror != 0)
|
||||||
|
{
|
||||||
|
cout << endl << "Check path to Matlab/octave on your system" << endl;
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// #####################################################################
|
||||||
|
Mesh_2d_3_square::Mesh_2d_3_square(int nx, int ny, int myid, int procx, int procy)
|
||||||
|
: Mesh(2, 3, 3), // two dimensions, 3 vertices, 3 dofs
|
||||||
|
_myid(myid), _procx(procx), _procy(procy), _neigh{{-1, -1, -1, -1}}, _color(0),
|
||||||
|
_xl(0.0), _xr(1.0), _yb(0.0), _yt(1.0), _nx(nx), _ny(ny)
|
||||||
|
{
|
||||||
|
//void IniGeom(int const myid, int const procx, int const procy, int neigh[], int &color)
|
||||||
|
int const ky = _myid / _procx;
|
||||||
|
int const kx = _myid % _procy; // MOD(myid,procx)
|
||||||
|
// Determine the neighbors of domain/rank myid
|
||||||
|
_neigh[0] = (ky == 0) ? -1 : _myid - _procx; // South
|
||||||
|
_neigh[1] = (kx == _procx - 1) ? -1 : _myid + 1; // East
|
||||||
|
_neigh[2] = (ky == _procy - 1) ? -1 : _myid + _procx; // North
|
||||||
|
_neigh[3] = (kx == 0) ? -1 : _myid - 1; // West
|
||||||
|
|
||||||
|
_color = (kx + ky) & 1 ;
|
||||||
|
|
||||||
|
// subdomain is part of unit square
|
||||||
|
double const hx = 1. / _procx;
|
||||||
|
double const hy = 1. / _procy;
|
||||||
|
_xl = kx * hx; // left
|
||||||
|
_xr = (kx + 1) * hx; // right
|
||||||
|
_yb = ky * hy; // bottom
|
||||||
|
_yt = (ky + 1) * hy; // top
|
||||||
|
|
||||||
|
// Calculate coordinates
|
||||||
|
int const nnode = (_nx + 1) * (_ny + 1); // number of nodes
|
||||||
|
Resize_Coords(nnode, 2); // coordinates in 2D [nnode][ndim]
|
||||||
|
GetCoordsInRectangle(_nx, _ny, _xl, _xr, _yb, _yt, GetCoords().data());
|
||||||
|
|
||||||
|
// Calculate element connectivity (linear triangles)
|
||||||
|
int const nelem = 2 * _nx * _ny; // number of elements
|
||||||
|
Resize_Connectivity(nelem, 3); // connectivity matrix [nelem][3]
|
||||||
|
GetConnectivityInRectangle(_nx, _ny, GetConnectivity().data());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Mesh_2d_3_square::SetU(std::vector<double> &u) const
|
||||||
|
{
|
||||||
|
int dx = _nx + 1;
|
||||||
|
for (int j = 0; j <= _ny; ++j)
|
||||||
|
{
|
||||||
|
int k = j * dx;
|
||||||
|
for (int i = 0; i <= _nx; ++i, ++k)
|
||||||
|
{
|
||||||
|
u[k] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh_2d_3_square::SetF(std::vector<double> &f) const
|
||||||
|
{
|
||||||
|
int dx = _nx + 1;
|
||||||
|
for (int j = 0; j <= _ny; ++j)
|
||||||
|
{
|
||||||
|
int k = j * dx;
|
||||||
|
for (int i = 0; i <= _nx; ++i, ++k)
|
||||||
|
{
|
||||||
|
f[k] = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<int> Mesh_2d_3_square::Index_DirichletNodes() const
|
||||||
|
{
|
||||||
|
int const dx = 1,
|
||||||
|
dy = _nx + 1,
|
||||||
|
bl = 0,
|
||||||
|
br = _nx,
|
||||||
|
tl = _ny * (_nx + 1),
|
||||||
|
tr = (_ny + 1) * (_nx + 1) - 1;
|
||||||
|
int const start[4] = { bl, br, tl, bl},
|
||||||
|
end[4] = { br, tr, tr, tl},
|
||||||
|
step[4] = { dx, dy, dx, dy};
|
||||||
|
|
||||||
|
vector<int> idx(0);
|
||||||
|
for (int j = 0; j < 4; j++)
|
||||||
|
{
|
||||||
|
if (_neigh[j] < 0)
|
||||||
|
{
|
||||||
|
for (int i = start[j]; i <= end[j]; i += step[j])
|
||||||
|
{
|
||||||
|
idx.push_back(i); // node i is Dirichlet node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// remove multiple elements
|
||||||
|
sort(idx.begin(), idx.end()); // sort
|
||||||
|
idx.erase( unique(idx.begin(), idx.end()), idx.end() ); // remove duplicate data
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh_2d_3_square::SaveVectorP(std::string const &name, vector<double> const &u) const
|
||||||
|
{
|
||||||
|
// construct the file name for subdomain myid
|
||||||
|
const string tmp( std::to_string(_myid / 100) + to_string((_myid % 100) / 10) + to_string(_myid % 10) );
|
||||||
|
|
||||||
|
const string namep = name + "." + tmp;
|
||||||
|
ofstream ff(namep.c_str());
|
||||||
|
ff.precision(6);
|
||||||
|
ff.setf(ios::fixed, ios::floatfield);
|
||||||
|
|
||||||
|
// assumes tensor product grid in unit square; rowise numbered (as generated in class constructor)
|
||||||
|
// output is provided for tensor product grid visualization ( similar to Matlab-surf() )
|
||||||
|
auto const &xc = GetCoords();
|
||||||
|
int k = 0;
|
||||||
|
for (int j = 0; j <= _ny; ++j)
|
||||||
|
{
|
||||||
|
for (int i = 0; i <= _nx; ++i, ++k)
|
||||||
|
ff << xc[2 * k + 0] << " " << xc[2 * k + 1] << " " << u[k] << endl;
|
||||||
|
ff << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
ff.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh_2d_3_square::GetCoordsInRectangle(int const nx, int const ny,
|
||||||
|
double const xl, double const xr, double const yb, double const yt,
|
||||||
|
double xc[])
|
||||||
|
{
|
||||||
|
const double hx = (xr - xl) / nx,
|
||||||
|
hy = (yt - yb) / ny;
|
||||||
|
|
||||||
|
int k = 0;
|
||||||
|
for (int j = 0; j <= ny; ++j)
|
||||||
|
{
|
||||||
|
const double y0 = yb + j * hy;
|
||||||
|
for (int i = 0; i <= nx; ++i, k += 2)
|
||||||
|
{
|
||||||
|
xc[k ] = xl + i * hx;
|
||||||
|
xc[k + 1] = y0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh_2d_3_square::GetConnectivityInRectangle(int const nx, int const ny, int ia[])
|
||||||
|
{
|
||||||
|
const int dx = nx + 1;
|
||||||
|
int k = 0;
|
||||||
|
int l = 0;
|
||||||
|
for (int j = 0; j < ny; ++j, ++k)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nx; ++i, ++k)
|
||||||
|
{
|
||||||
|
ia[l ] = k;
|
||||||
|
ia[l + 1] = k + 1;
|
||||||
|
ia[l + 2] = k + dx + 1;
|
||||||
|
l += 3;
|
||||||
|
ia[l ] = k;
|
||||||
|
ia[l + 1] = k + dx;
|
||||||
|
ia[l + 2] = k + dx + 1;
|
||||||
|
l += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #################### still some old code (--> MPI) ############################
|
||||||
|
|
||||||
|
|
||||||
|
// Copies the values of w corresponding to the boundary
|
||||||
|
// South (ib==1), East (ib==2), North (ib==3), West (ib==4)
|
||||||
|
|
||||||
|
void GetBound(int const ib, int const nx, int const ny, double const w[], double s[])
|
||||||
|
{
|
||||||
|
const int //dx = 1,
|
||||||
|
dy = nx + 1,
|
||||||
|
bl = 0,
|
||||||
|
br = nx,
|
||||||
|
tl = ny * (nx + 1),
|
||||||
|
tr = (ny + 1) * (nx + 1) - 1;
|
||||||
|
switch (ib)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
for (int i = bl, j = 0; i <= br; ++i, ++j)
|
||||||
|
s[j] = w[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
for (int i = tl, j = 0; i <= tr; ++i, ++j)
|
||||||
|
s[j] = w[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
for (int i = bl, j = 0; i <= tl; i += dy, ++j)
|
||||||
|
s[j] = w[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
for (int i = br, j = 0; i <= tr; i += dy, ++j)
|
||||||
|
s[j] = w[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
cout << endl << "Wrong parameter ib in " << __FILE__ << ":" << __LINE__ << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------------------------
|
||||||
|
// Computes w: = w + s at nodes on the boundary
|
||||||
|
// South (ib == 1), East (ib == 2), North (ib == 3), West (ib == 4)
|
||||||
|
|
||||||
|
void AddBound(int const ib, int const nx, int const ny, double w[], double const s[])
|
||||||
|
{
|
||||||
|
int const dy = nx + 1,
|
||||||
|
bl = 0,
|
||||||
|
br = nx,
|
||||||
|
tl = ny * (nx + 1),
|
||||||
|
tr = (ny + 1) * (nx + 1) - 1;
|
||||||
|
switch (ib)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
for (int i = bl, j = 0; i <= br; ++i, ++j)
|
||||||
|
w[i] += s[j];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
for (int i = tl, j = 0; i <= tr; ++i, ++j)
|
||||||
|
w[i] += s[j];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
for (int i = bl, j = 0; i <= tl; i += dy, ++j)
|
||||||
|
w[i] += s[j];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
for (int i = br, j = 0; i <= tr; i += dy, ++j)
|
||||||
|
w[i] += s[j];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
cout << endl << "Wrong parameter ib in " << __FILE__ << ":" << __LINE__ << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ####################################################################
|
||||||
|
|
||||||
|
Mesh_2d_3_matlab::Mesh_2d_3_matlab(string const &fname)
|
||||||
|
: Mesh(2, 3, 3), // two dimensions, 3 vertices, 3 dofs
|
||||||
|
bedges(0)
|
||||||
|
{
|
||||||
|
ifstream ifs(fname);
|
||||||
|
if (!(ifs.is_open() && ifs.good()))
|
||||||
|
{
|
||||||
|
cerr << "Mesh_2d_3_matlab: Error cannot open file " << fname << endl;
|
||||||
|
assert(ifs.is_open());
|
||||||
|
}
|
||||||
|
|
||||||
|
int const OFFSET(1); // Matlab to C indexing
|
||||||
|
cout << "ASCI file " << fname << " opened" << endl;
|
||||||
|
|
||||||
|
// Read some mesh constants
|
||||||
|
int nnode, ndim, nelem, nvert_e;
|
||||||
|
ifs >> nnode >> ndim >> nelem >> nvert_e;
|
||||||
|
cout << nnode << " " << ndim << " " << nelem << " " << nvert_e << endl;
|
||||||
|
assert(ndim == 2 && nvert_e == 3);
|
||||||
|
|
||||||
|
// Allocate memory
|
||||||
|
Resize_Coords(nnode, ndim); // coordinates in 2D [nnode][ndim]
|
||||||
|
Resize_Connectivity(nelem, nvert_e); // connectivity matrix [nelem][nvert]
|
||||||
|
|
||||||
|
// Read ccordinates
|
||||||
|
auto &xc = GetCoords();
|
||||||
|
for (int k = 0; k < nnode * ndim; ++k)
|
||||||
|
{
|
||||||
|
ifs >> xc[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read connectivity
|
||||||
|
auto &ia = GetConnectivity();
|
||||||
|
for (int k = 0; k < nelem * nvert_e; ++k)
|
||||||
|
{
|
||||||
|
ifs >> ia[k];
|
||||||
|
ia[k] -= OFFSET; // Matlab to C indexing
|
||||||
|
}
|
||||||
|
|
||||||
|
// additional read of boundary information (only start/end point)
|
||||||
|
int nbedges;
|
||||||
|
ifs >> nbedges;
|
||||||
|
|
||||||
|
bedges.resize(nbedges * 2);
|
||||||
|
for (int k = 0; k < nbedges * 2; ++k)
|
||||||
|
{
|
||||||
|
ifs >> bedges[k];
|
||||||
|
bedges[k] -= OFFSET; // Matlab to C indexing
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// binary
|
||||||
|
//{
|
||||||
|
//ifstream ifs(fname, ios_base::in | ios_base::binary);
|
||||||
|
//if(!(ifs.is_open() && ifs.good()))
|
||||||
|
//{
|
||||||
|
//cerr << "ReadBinMatrix: Error cannot open file " << file << endl;
|
||||||
|
//assert(ifs.is_open());
|
||||||
|
//}
|
||||||
|
//cout << "ReadBinMatrix: file opened" << file << endl;
|
||||||
|
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
// binaryIO.cpp
|
||||||
|
//void read_binMatrix(const string& file, vector<int> &cnt, vector<int> &col, vector<double> &ele)
|
||||||
|
//{
|
||||||
|
|
||||||
|
//ifstream ifs(file, ios_base::in | ios_base::binary);
|
||||||
|
|
||||||
|
//if(!(ifs.is_open() && ifs.good()))
|
||||||
|
//{
|
||||||
|
//cerr << "ReadBinMatrix: Error cannot open file " << file << endl;
|
||||||
|
//assert(ifs.is_open());
|
||||||
|
//}
|
||||||
|
//cout << "ReadBinMatrix: Opened file " << file << endl;
|
||||||
|
|
||||||
|
//int _size;
|
||||||
|
|
||||||
|
//ifs.read(reinterpret_cast<char*>(&_size), sizeof(int)); // old: ifs.read((char*)&_size, sizeof(int));
|
||||||
|
//cnt.resize(_size);
|
||||||
|
//cout << "ReadBinMatrix: cnt size: " << _size << endl;
|
||||||
|
|
||||||
|
//ifs.read((char*)&_size, sizeof(int));
|
||||||
|
//col.resize(_size);
|
||||||
|
//cout << "ReadBinMatrix: col size: " << _size << endl;
|
||||||
|
|
||||||
|
//ifs.read((char*)&_size, sizeof(int));
|
||||||
|
//ele.resize(_size);
|
||||||
|
//cout << "ReadBinMatrix: ele size: " << _size << endl;
|
||||||
|
|
||||||
|
|
||||||
|
//ifs.read((char*)cnt.data(), cnt.size() * sizeof(int));
|
||||||
|
//ifs.read((char*)col.data(), col.size() * sizeof(int));
|
||||||
|
//ifs.read((char*)ele.data(), ele.size() * sizeof(double));
|
||||||
|
|
||||||
|
//ifs.close();
|
||||||
|
//cout << "ReadBinMatrix: Finished reading matrix.." << endl;
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<int> Mesh_2d_3_matlab::Index_DirichletNodes() const
|
||||||
|
{
|
||||||
|
vector<int> idx(bedges); // copy
|
||||||
|
|
||||||
|
sort(idx.begin(), idx.end()); // sort
|
||||||
|
idx.erase( unique(idx.begin(), idx.end()), idx.end() ); // remove duplicate data
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
0
sheet5/5/geom.cpp:Zone.Identifier
Normal file
0
sheet5/5/geom.cpp:Zone.Identifier
Normal file
381
sheet5/5/geom.h
Normal file
381
sheet5/5/geom.h
Normal file
|
|
@ -0,0 +1,381 @@
|
||||||
|
#ifndef GEOM_FILE
|
||||||
|
#define GEOM_FILE
|
||||||
|
#include <array>
|
||||||
|
#include <functional> // function; C++11
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basis class for finite element meshes.
|
||||||
|
*/
|
||||||
|
class Mesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructor initializing the members with default values.
|
||||||
|
*
|
||||||
|
* @param[in] ndim space dimensions (dimension for coordinates)
|
||||||
|
* @param[in] nvert_e number of vertices per element (dimension for connectivity)
|
||||||
|
* @param[in] ndof_e degrees of freedom per element (= @p nvert_e for linear elements)
|
||||||
|
*/
|
||||||
|
explicit Mesh(int ndim, int nvert_e = 0, int ndof_e = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*
|
||||||
|
* See clang warning on
|
||||||
|
* <a href="https://stackoverflow.com/questions/28786473/clang-no-out-of-line-virtual-method-definitions-pure-abstract-c-class/40550578">weak-vtables</a>.
|
||||||
|
*/
|
||||||
|
virtual ~Mesh();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of finite elements in (sub)domain.
|
||||||
|
* @return number of elements.
|
||||||
|
*/
|
||||||
|
int Nelems() const
|
||||||
|
{
|
||||||
|
return _nelem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global number of vertices for each finite element.
|
||||||
|
* @return number of vertices per element.
|
||||||
|
*/
|
||||||
|
int NverticesElements() const
|
||||||
|
{
|
||||||
|
return _nvert_e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global number of degrees of freedom (dof) for each finite element.
|
||||||
|
* @return degrees of freedom per element.
|
||||||
|
*/
|
||||||
|
int NdofsElement() const
|
||||||
|
{
|
||||||
|
return _ndof_e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of vertices in mesh.
|
||||||
|
* @return number of vertices.
|
||||||
|
*/
|
||||||
|
int Nnodes() const
|
||||||
|
{
|
||||||
|
return _nnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Space dimension.
|
||||||
|
* @return number of dimensions.
|
||||||
|
*/
|
||||||
|
int Ndims() const
|
||||||
|
{
|
||||||
|
return _ndim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Re-)Allocates memory for the element connectivity and redefines the appropriate dimensions.
|
||||||
|
*
|
||||||
|
* @param[in] nelem number of elements
|
||||||
|
* @param[in] nvert_e number of vertices per element
|
||||||
|
*/
|
||||||
|
void Resize_Connectivity(int nelem, int nvert_e)
|
||||||
|
{
|
||||||
|
SetNelem(nelem); // number of elements
|
||||||
|
SetNverticesElement(nvert_e); // vertices per element
|
||||||
|
_ia.resize(nelem * nvert_e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read connectivity information (g1,g2,g3)_i.
|
||||||
|
* @return convectivity vector [nelems*ndofs].
|
||||||
|
*/
|
||||||
|
const std::vector<int> &GetConnectivity() const
|
||||||
|
{
|
||||||
|
return _ia;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access/Change connectivity information (g1,g2,g3)_i.
|
||||||
|
* @return convectivity vector [nelems*ndofs].
|
||||||
|
*/
|
||||||
|
std::vector<int> &GetConnectivity()
|
||||||
|
{
|
||||||
|
return _ia;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Re-)Allocates memory for the element connectivity and redefines the appropriate dimensions.
|
||||||
|
*
|
||||||
|
* @param[in] nnodes number of nodes
|
||||||
|
* @param[in] ndim space dimension
|
||||||
|
*/
|
||||||
|
void Resize_Coords(int nnodes, int ndim)
|
||||||
|
{
|
||||||
|
SetNnode(nnodes); // number of nodes
|
||||||
|
SetNdim(ndim); // space dimension
|
||||||
|
_xc.resize(nnodes * ndim);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read coordinates of vertices (x,y)_i.
|
||||||
|
* @return coordinates vector [nnodes*2].
|
||||||
|
*/
|
||||||
|
const std::vector<double> &GetCoords() const
|
||||||
|
{
|
||||||
|
return _xc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access/Change coordinates of vertices (x,y)_i.
|
||||||
|
* @return coordinates vector [nnodes*2].
|
||||||
|
*/
|
||||||
|
std::vector<double> &GetCoords()
|
||||||
|
{
|
||||||
|
return _xc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate values in vector @p v via function @p func(x,y)
|
||||||
|
* @param[in] v vector
|
||||||
|
* @param[in] func function of (x,y) returning a double value.
|
||||||
|
*/
|
||||||
|
void SetValues(std::vector<double> &v, const std::function<double(double, double)> &func) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the information for a finite element mesh
|
||||||
|
*/
|
||||||
|
void Debug() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the indices of those vertices with Dirichlet boundary conditions
|
||||||
|
* @return index vector.
|
||||||
|
*/
|
||||||
|
virtual std::vector<int> Index_DirichletNodes() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write vector @p v toghether with its mesh information to an ASCii file @p fname.
|
||||||
|
*
|
||||||
|
* The data are written in C-style.
|
||||||
|
*
|
||||||
|
* @param[in] fname file name
|
||||||
|
* @param[in] v vector
|
||||||
|
*/
|
||||||
|
void Write_ascii_matlab(std::string const &fname, std::vector<double> const &v) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visualize @p v together with its mesh information via matlab or octave.
|
||||||
|
*
|
||||||
|
* Comment/uncomment those code lines in method Mesh:Visualize (geom.cpp)
|
||||||
|
* that are supported on your system.
|
||||||
|
*
|
||||||
|
* @param[in] v vector
|
||||||
|
*
|
||||||
|
* @warning matlab files ascii_read_meshvector.m visualize_results.m
|
||||||
|
* must be in the executing directory.
|
||||||
|
*/
|
||||||
|
void Visualize(std::vector<double> const &v) const;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void SetNelem(int nelem)
|
||||||
|
{
|
||||||
|
_nelem = nelem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNverticesElement(int nvert)
|
||||||
|
{
|
||||||
|
_nvert_e = nvert;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNdofsElement(int ndof)
|
||||||
|
{
|
||||||
|
_ndof_e = ndof;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNnode(int nnode)
|
||||||
|
{
|
||||||
|
_nnode = nnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNdim(int ndim)
|
||||||
|
{
|
||||||
|
_ndim = ndim;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _nelem; //!< number elements
|
||||||
|
int _nvert_e; //!< number of vertices per element
|
||||||
|
int _ndof_e; //!< degrees of freedom (d.o.f.) per element
|
||||||
|
int _nnode; //!< number nodes/vertices
|
||||||
|
int _ndim; //!< space dimension of the problem (1, 2, or 3)
|
||||||
|
std::vector<int> _ia; //!< element connectivity
|
||||||
|
std::vector<double> _xc; //!< coordinates
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2D finite element mesh of the square consiting of linear triangular elements.
|
||||||
|
*/
|
||||||
|
class Mesh_2d_3_square: public Mesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Generates the f.e. mesh for the unit square.
|
||||||
|
*
|
||||||
|
* @param[in] nx number of discretization intervals in x-direction
|
||||||
|
* @param[in] ny number of discretization intervals in y-direction
|
||||||
|
* @param[in] myid my MPI-rank / subdomain
|
||||||
|
* @param[in] procx number of ranks/subdomains in x-direction
|
||||||
|
* @param[in] procy number of processes in y-direction
|
||||||
|
*/
|
||||||
|
Mesh_2d_3_square(int nx, int ny, int myid = 0, int procx = 1, int procy = 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
|
~Mesh_2d_3_square() override
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set solution vector based on a tensor product grid in the rectangle.
|
||||||
|
* @param[in] u solution vector
|
||||||
|
*/
|
||||||
|
void SetU(std::vector<double> &u) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set right hand side (rhs) vector on a tensor product grid in the rectangle.
|
||||||
|
* @param[in] f rhs vector
|
||||||
|
*/
|
||||||
|
void SetF(std::vector<double> &f) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the indices of those vertices with Dirichlet boundary conditions
|
||||||
|
* @return index vector.
|
||||||
|
*/
|
||||||
|
std::vector<int> Index_DirichletNodes() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the values of vector @p u of (sub)domain into a file @p name for further processing in gnuplot.
|
||||||
|
* The file stores rowise the x- and y- coordinates together with the value from @p u .
|
||||||
|
* The domain [@p xl, @p xr] x [@p yb, @p yt] is discretized into @p nx x @p ny intervals.
|
||||||
|
*
|
||||||
|
* @param[in] name basename of file name (file name will be extended by the rank number)
|
||||||
|
* @param[in] u local vector
|
||||||
|
*
|
||||||
|
* @warning Assumes tensor product grid in unit square; rowise numbered
|
||||||
|
* (as generated in class constructor).
|
||||||
|
* The output is provided for tensor product grid visualization
|
||||||
|
* ( similar to Matlab-surf() ).
|
||||||
|
*
|
||||||
|
* @see Mesh_2d_3_square
|
||||||
|
*/
|
||||||
|
void SaveVectorP(std::string const &name, std::vector<double> const &u) const;
|
||||||
|
|
||||||
|
// here will still need to implement in the class
|
||||||
|
// GetBound(), AddBound()
|
||||||
|
// or better a generalized way with indices and their appropriate ranks for MPI communication
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Determines the coordinates of the dicretization nodes of the domain [@p xl, @p xr] x [@p yb, @p yt]
|
||||||
|
* which is discretized into @p nx x @p ny intervals.
|
||||||
|
*
|
||||||
|
* @param[in] ny number of discretization intervals in y-direction
|
||||||
|
* @param[in] xl x-coordinate of left boundary
|
||||||
|
* @param[in] xr x-coordinate of right boundary
|
||||||
|
* @param[in] yb y-coordinate of lower boundary
|
||||||
|
* @param[in] yt y-coordinate of upper boundary
|
||||||
|
* @param[out] xc coordinate vector of length 2n with x(2*k,2*k+1) as coodinates of node k
|
||||||
|
*/
|
||||||
|
|
||||||
|
void GetCoordsInRectangle(int nx, int ny, double xl, double xr, double yb, double yt,
|
||||||
|
double xc[]);
|
||||||
|
/**
|
||||||
|
* Determines the element connectivity of linear triangular elements of a FEM discretization
|
||||||
|
* of a rectangle using @p nx x @p ny equidistant intervals for discretization.
|
||||||
|
* @param[in] nx number of discretization intervals in x-direction
|
||||||
|
* @param[in] ny number of discretization intervals in y-direction
|
||||||
|
* @param[out] ia element connectivity matrix with ia(3*s,3*s+1,3*s+2) as node numbers od element s
|
||||||
|
*/
|
||||||
|
void GetConnectivityInRectangle(int nx, int ny, int ia[]);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _myid; //!< my MPI rank
|
||||||
|
int _procx; //!< number of MPI ranks in x-direction
|
||||||
|
int _procy; //!< number of MPI ranks in y-direction
|
||||||
|
std::array<int, 4> _neigh; //!< MPI ranks of neighbors (negative: no neighbor but b.c.)
|
||||||
|
int _color; //!< red/black coloring (checker board) of subdomains
|
||||||
|
|
||||||
|
double _xl; //!< x coordinate of lower left corner of square
|
||||||
|
double _xr; //!< x coordinate of lower right corner of square
|
||||||
|
double _yb; //!< y coordinate or lower left corner of square
|
||||||
|
double _yt; //!< y coordinate of upper right corner of square
|
||||||
|
int _nx; //!< number of intervals in x-direction
|
||||||
|
int _ny; //!< number of intervals in y-direction
|
||||||
|
};
|
||||||
|
|
||||||
|
// #################### still some old code (--> MPI) ############################
|
||||||
|
/**
|
||||||
|
* Copies the values of @p w corresponding to boundary @p ib
|
||||||
|
* onto vector s. South (ib==1), East (ib==2), North (ib==3), West (ib==4).
|
||||||
|
* The vector @p s has to be long enough!!
|
||||||
|
* @param[in] ib my local boundary
|
||||||
|
* @param[in] nx number of discretization intervals in x-direction
|
||||||
|
* @param[in] ny number of discretization intervals in y-direction
|
||||||
|
* @param[in] w vector for all nodes of local discretization
|
||||||
|
* @param[out] s short vector with values on boundary @p ib
|
||||||
|
*/
|
||||||
|
// GH_NOTE: Absicherung bei s !!
|
||||||
|
void GetBound(int ib, int nx, int ny, double const w[], double s[]);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes @p w := @p w + @p s at the interface/boundary nodes on the
|
||||||
|
* boundary @p ib . South (ib==1), East (ib==2), North (ib==3), West (ib==4)
|
||||||
|
* @param[in] ib my local boundary
|
||||||
|
* @param[in] nx number of discretization intervals in x-direction
|
||||||
|
* @param[in] ny number of discretization intervals in y-direction
|
||||||
|
* @param[in,out] w vector for all nodes of local discretization
|
||||||
|
* @param[in] s short vector with values on boundary @p ib
|
||||||
|
*/
|
||||||
|
void AddBound(int ib, int nx, int ny, double w[], double const s[]);
|
||||||
|
|
||||||
|
// #################### Mesh from Matlab ############################
|
||||||
|
/**
|
||||||
|
* 2D finite element mesh of the square consiting of linear triangular elements.
|
||||||
|
*/
|
||||||
|
class Mesh_2d_3_matlab: public Mesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Reads mesh data from a binary file.
|
||||||
|
*
|
||||||
|
* File format, see ascii_write_mesh.m
|
||||||
|
*
|
||||||
|
* @param[in] fname file name
|
||||||
|
*/
|
||||||
|
explicit Mesh_2d_3_matlab(std::string const &fname);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the indices of those vertices with Dirichlet boundary conditions.
|
||||||
|
* @return index vector.
|
||||||
|
*
|
||||||
|
* @warning All boundary nodes are considered as Dirchlet nodes.
|
||||||
|
*/
|
||||||
|
std::vector<int> Index_DirichletNodes() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Determines the indices of those vertices with Dirichlet boundary conditions
|
||||||
|
* @return index vector.
|
||||||
|
*/
|
||||||
|
int Nnbedges() const
|
||||||
|
{
|
||||||
|
return static_cast<int>(bedges.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> bedges; //!< boundary edges [nbedges][2] storing start/end vertex
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
0
sheet5/5/geom.h:Zone.Identifier
Normal file
0
sheet5/5/geom.h:Zone.Identifier
Normal file
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue