FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
NetThreads.h
1#pragma once
2
3#include <algorithm>
4#include <fhsim/simobject/ISimObjectCreator.h>
5#include <stdexcept>
6#include <string>
7#include <vector>
8
9#ifdef _OPENMP
10# include <omp.h>
11#endif
12
21namespace net_threads
22{
27inline int ReadNumThreads(ISimObjectCreator* creator)
28{
29 int numThreads = 1;
30 creator->GetIntParam("NumThreads", &numThreads, numThreads);
31 if (numThreads < 0) {
32 const std::string message = "NumThreads = " + std::to_string(numThreads) + " is negative; expected 0 (OpenMP's default), 1 (serial) or more.";
33 creator->ReportParameterError("NumThreads", message);
34 throw std::invalid_argument(message);
35 }
36#ifdef _OPENMP
37 if (numThreads == 0)
38 numThreads = omp_get_max_threads();
39#else
40 numThreads = 1; // built without OpenMP
41#endif
42 return std::max(numThreads, 1);
43}
44
46inline int ChunkBegin(const int count, const int chunk, const int chunks)
47{
48 return count * chunk / chunks;
49}
50
60template <class UpdateNodes, class AddForces>
61void SumForcesInChunks(const int chunks, const int numNodes, std::vector<double>& buffers, double* const nodeForce, UpdateNodes updateNodes, AddForces addForces)
62{
63 const size_t bufferSize = 3 * static_cast<size_t>(numNodes);
64#ifdef _OPENMP
65# pragma omp parallel num_threads(chunks)
66#endif
67 {
68#ifdef _OPENMP
69 const int first = omp_get_thread_num();
70 const int stride = omp_get_num_threads();
71#else
72 const int first = 0;
73 const int stride = 1;
74#endif
75 for (int chunk = first; chunk < chunks; chunk += stride)
76 updateNodes(ChunkBegin(numNodes, chunk, chunks), ChunkBegin(numNodes, chunk + 1, chunks));
77#ifdef _OPENMP
78# pragma omp barrier
79#endif
80 for (int chunk = first; chunk < chunks; chunk += stride) {
81 double* const forces = buffers.data() + chunk * bufferSize;
82 std::fill(forces, forces + bufferSize, 0.0);
83 addForces(chunk, chunks, forces);
84 }
85 }
86 for (int chunk = 0; chunk < chunks; chunk++) {
87 const double* const forces = buffers.data() + chunk * bufferSize;
88 for (size_t i = 0; i < bufferSize; i++)
89 nodeForce[i] += forces[i];
90 }
91}
92} // namespace net_threads