27 #ifdef GETFEM_HAVE_OPENMP 29 boost::recursive_mutex omp_guard::boost_mutex;
31 omp_guard::omp_guard()
32 :
boost::lock_guard<
boost::recursive_mutex>(boost_mutex)
35 local_guard::local_guard(boost::recursive_mutex& m) :
37 plock_(new
boost::lock_guard<
boost::recursive_mutex>(m))
40 local_guard::local_guard(
const local_guard& guard)
41 : mutex_(guard.mutex_), plock_(guard.plock_)
44 lock_factory::lock_factory() : mutex_() {}
45 local_guard lock_factory::get_lock()
const 47 return local_guard(mutex_);
51 omp_distribute<bool> open_mp_is_running_properly::answer =
false;
52 open_mp_is_running_properly::open_mp_is_running_properly()
53 {answer.all_threads()=
true;}
54 open_mp_is_running_properly::~open_mp_is_running_properly()
55 {answer.all_threads()=
false;}
56 bool open_mp_is_running_properly::is_it(){
return answer;}
58 region_partition::region_partition(
const region_partition& rp) :
59 pparent_mesh(rp.pparent_mesh),
60 original_region(rp.original_region),
61 partitions(rp.partitions) { }
63 void region_partition::operator=(
const region_partition& rp)
67 if (!rp.pparent_mesh)
return;
68 pparent_mesh->
copy_from(*rp.pparent_mesh);
69 original_region = rp.original_region;
70 partitions.resize(rp.partitions.size());
71 gmm::copy(rp.partitions,partitions);
75 region_partition::region_partition(mesh* pm,
size_type id) :
76 pparent_mesh(pm),original_region(0),
77 partitions(num_threads())
79 scalar_type time = gmm::uclock_sec();
81 if (num_threads()==1) {partitions[0]=id;
return;}
87 original_region.reset(
new mesh_region(pm->convex_index()));
88 original_region->set_parent_mesh(pm);
90 GMM_ASSERT1(pm->has_region(
id),
"Improper region number");
91 original_region.reset(
new mesh_region(pm->region(
id)));
93 if (me_is_multithreaded_now())
94 GMM_WARNING0(
"building partitions inside parallel region");
96 omp_guard scoped_lock;
97 GMM_NOPERATION(scoped_lock);
98 size_type Nelems = original_region->size();
100 (std::ceil(static_cast<scalar_type >(Nelems)/
101 static_cast<scalar_type >(num_threads())));
102 mr_visitor mr(*original_region);
103 for(
size_type thread = 0; thread<num_threads();thread++)
107 mesh_region partition;
108 for(
size_type i=thread*psize;i<(thread+1)*psize && !mr.finished();i++,++mr)
110 if (mr.is_face()) partition.add(mr.cv(),mr.f());
111 else partition.add(mr.cv());
113 pparent_mesh->region(partitions[thread]) = partition;
115 GMM_TRACE2(
"Partitioning time: "<<gmm::uclock_sec()-time<<
" s.");
119 thread_local_partition()
const {
120 if (pparent_mesh==0 && num_threads() >1 ){
121 GMM_WARNING1(
"partition is empty and cannot be used \ 122 this means that the brick that created it should partition \ 123 its domain by himself");
126 return partitions[this_thread()];
129 void omp_distribute<bool>::all_values_proxy::operator=(
const bool& x)
131 for(std::vector<BOOL>::iterator it=distro.thread_values.begin();
132 it!=distro.thread_values.end();it++) *it=x;
136 thread_exception::thread_exception(): exceptions_(num_threads(), nullptr)
143 std::vector<std::exception_ptr> exceptions;
144 for (
auto &&pException : exceptions_)
146 if (pException !=
nullptr) exceptions.push_back(pException);
151 void thread_exception::rethrow()
153 for (
auto &&pException : exceptions_)
155 if (pException !=
nullptr) std::rethrow_exception(pException);
159 void thread_exception::captureException()
161 exceptions_[this_thread()] = std::current_exception();
Define a getfem::getfem_mesh object.
Tools for multithreaded, OpenMP and Boost based parallelization.
static size_type free_region_id(const getfem::mesh &m)
Extract the next region number that does not yet exists in the mesh.
size_t size_type
used as the common size type in the library
void copy_from(const mesh &m)
Clone a mesh.
GEneric Tool for Finite Element Methods.
~thread_exception()
re-throws the first captured exception
std::vector< std::exception_ptr > caughtExceptions() const
vector of pointers to caught exceptions