15#include <range/v3/view/iota.hpp>
29 const std::size_t mesh_item_id,
33 std::vector<double>& local_b_data, std::vector<double>& local_Jac_data,
37 std::vector<GlobalIndexType>
const& indices =
41 local_Jac_data.clear();
43 auto const local_x = x.
get(indices);
44 auto const local_x_prev = x_prev.
get(indices);
46 local_x_prev, local_b_data,
49 if (local_Jac_data.empty())
52 "No Jacobian has been assembled! This might be due to "
53 "programming errors in the local assembler of the "
57 cache.
add(local_b_data, local_Jac_data, indices);
61 const std::size_t mesh_item_id,
63 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& dof_tables,
64 const double t,
const double dt, std::vector<GlobalVector*>
const& x,
65 std::vector<GlobalVector*>
const& x_prev,
int const process_id,
66 std::vector<double>& local_b_data, std::vector<double>& local_Jac_data,
70 std::vector<std::vector<GlobalIndexType>> indices_of_processes;
71 indices_of_processes.reserve(dof_tables.size());
72 transform(cbegin(dof_tables), cend(dof_tables),
73 back_inserter(indices_of_processes),
74 [&](
auto const* dof_table)
77 auto local_coupled_xs =
81 auto local_coupled_x_prevs =
85 std::vector<GlobalIndexType>
const& indices =
86 indices_of_processes[process_id];
89 local_Jac_data.clear();
92 local_assembler, t, dt, local_x, local_x_prev, process_id, local_b_data,
95 if (local_Jac_data.empty())
98 "No Jacobian has been assembled! This might be due to "
99 "programming errors in the local assembler of the "
103 cache.
add(local_b_data, local_Jac_data, indices);
108 std::tuple<std::ptrdiff_t,
109 std::reference_wrapper<ProcessLib::LocalAssemblerInterface>>>
113 std::vector<std::size_t>
const& active_elements)
115 auto create_ids_asm_pairs = [&](
auto const& element_ids)
117 std::vector<std::tuple<
119 std::reference_wrapper<ProcessLib::LocalAssemblerInterface>>>
121 result.reserve(
static_cast<std::size_t
>(element_ids.size()));
122 for (
auto const id : element_ids)
124 result.push_back({id, local_assemblers[id]});
129 if (active_elements.empty())
131 return create_ids_asm_pairs(ranges::views::iota(
132 static_cast<std::size_t
>(0), local_assemblers.size()));
134 return create_ids_asm_pairs(active_elements);
138 std::vector<std::tuple<
140 std::reference_wrapper<ProcessLib::LocalAssemblerInterface>>>
const&
141 ids_local_assemblers,
143 auto local_matrix_output,
146 std::ptrdiff_t n_elements =
147 static_cast<std::ptrdiff_t
>(ids_local_assemblers.size());
149#pragma omp for nowait
150 for (std::ptrdiff_t i = 0; i < n_elements; ++i)
156 auto [element_id, loc_asm] = ids_local_assemblers[i];
160 assemble(element_id, loc_asm);
168 local_matrix_output(element_id);
174 char const*
const num_threads_env = std::getenv(
"OGS_ASM_THREADS");
176 if (!num_threads_env)
181 if (std::strlen(num_threads_env) == 0)
183 OGS_FATAL(
"The environment variable OGS_ASM_THREADS is set but empty.");
186 std::string num_threads_str{num_threads_env};
189 std::istringstream num_threads_iss{num_threads_str};
190 int num_threads = -1;
192 num_threads_iss >> num_threads;
194 if (!num_threads_iss)
196 OGS_FATAL(
"Error parsing OGS_ASM_THREADS (= \"{}\").", num_threads_env);
199 if (!num_threads_iss.eof())
202 "Error parsing OGS_ASM_THREADS (= \"{}\"): not read entirely, the "
203 "remainder is \"{}\"",
205 num_threads_iss.str().substr(num_threads_iss.tellg()));
211 "You asked (via OGS_ASM_THREADS) to assemble with {} < 1 thread.",
223 : jacobian_assembler_{jacobian_assembler},
224 num_threads_(getNumberOfThreads())
231 std::vector<std::size_t>
const& active_elements,
232 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& dof_tables,
233 const double t,
double const dt, std::vector<GlobalVector*>
const& xs,
234 std::vector<GlobalVector*>
const& x_prevs,
int const process_id,
238 if (dof_tables.size() != xs.size())
240 OGS_FATAL(
"Different number of DOF tables and solution vectors.");
243 std::size_t
const number_of_processes = xs.size();
251#pragma omp parallel num_threads(num_threads_)
254#pragma omp single nowait
256 INFO(
"Number of threads: {}", omp_get_num_threads());
262 std::vector<double> local_b_data;
263 std::vector<double> local_Jac_data;
267 auto stats_this_thread = stats->clone();
270 stats_this_thread->data};
272 auto local_matrix_output = [&](std::ptrdiff_t element_id)
281 if (number_of_processes == 1)
283 assert(process_id == 0);
284 auto const& dof_table = *dof_tables[0];
285 auto const& x = *xs[0];
286 auto const& x_prev = *x_prevs[0];
289 collectActiveLocalAssemblers(local_assemblers, active_elements),
290 exception, local_matrix_output,
291 [&](
auto element_id,
auto& loc_asm)
293 assembleWithJacobianOneElement(
294 element_id, loc_asm, dof_table, t, dt, x, x_prev,
295 local_b_data, local_Jac_data, *jac_asm, cache);
301 collectActiveLocalAssemblers(local_assemblers, active_elements),
302 exception, local_matrix_output,
303 [&](
auto element_id,
auto& loc_asm)
305 assembleWithJacobianForStaggeredSchemeOneElement(
306 element_id, loc_asm, dof_tables, t, dt, xs, x_prevs,
307 process_id, local_b_data, local_Jac_data, *jac_asm,
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Global vector based on Eigen vector.
double get(IndexType rowId) const
get entry
Base class for Jacobian assemblers.
virtual void assembleWithJacobian(LocalAssemblerInterface &local_assembler, double const t, double const dt, std::vector< double > const &local_x, std::vector< double > const &local_x_prev, std::vector< double > &local_b_data, std::vector< double > &local_Jac_data)=0
virtual std::unique_ptr< AbstractJacobianAssembler > copy() const =0
virtual void assembleWithJacobianForStaggeredScheme(LocalAssemblerInterface &, double const, double const, Eigen::VectorXd const &, Eigen::VectorXd const &, int const, std::vector< double > &, std::vector< double > &)
static std::shared_ptr< CumulativeStats< Data > > create()
void add(std::vector< double > const &local_b_data, std::vector< double > const &local_Jac_data, std::vector< GlobalIndexType > const &indices)
LocalMatrixOutput local_matrix_output_
GlobalMatrixOutput global_matrix_output_
AbstractJacobianAssembler & jacobian_assembler_
ParallelVectorMatrixAssembler(AbstractJacobianAssembler &jacobian_assembler)
void assembleWithJacobian(BaseLib::PolymorphicRandomAccessContainerView< LocalAssemblerInterface > const &local_assemblers, std::vector< std::size_t > const &active_elements, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_tables, const double t, double const dt, std::vector< GlobalVector * > const &xs, std::vector< GlobalVector * > const &x_prevs, int const process_id, GlobalVector &b, GlobalMatrix &Jac)
void trim(std::string &str, char ch)
Eigen::Map< const Vector > toVector(std::vector< double > const &data, Eigen::VectorXd::Index size)
Creates an Eigen mapped vector from the given data vector.
std::vector< GlobalIndexType > getIndices(std::size_t const mesh_item_id, NumLib::LocalToGlobalIndexMap const &dof_table)
std::vector< double > getCoupledLocalSolutions(std::vector< GlobalVector * > const &global_solutions, std::vector< std::vector< GlobalIndexType > > const &indices)
std::vector< std::tuple< std::ptrdiff_t, std::reference_wrapper< ProcessLib::LocalAssemblerInterface > > > collectActiveLocalAssemblers(BaseLib::PolymorphicRandomAccessContainerView< ProcessLib::LocalAssemblerInterface > const &local_assemblers, std::vector< std::size_t > const &active_elements)
Returns a vector of active element ids with corresponding local assemblers.
void assembleWithJacobianOneElement(const std::size_t mesh_item_id, ProcessLib::LocalAssemblerInterface &local_assembler, const NumLib::LocalToGlobalIndexMap &dof_table, const double t, const double dt, const GlobalVector &x, const GlobalVector &x_prev, std::vector< double > &local_b_data, std::vector< double > &local_Jac_data, ProcessLib::AbstractJacobianAssembler &jacobian_assembler, ProcessLib::Assembly::MultiMatrixElementCache &cache)
void assembleWithJacobianForStaggeredSchemeOneElement(const std::size_t mesh_item_id, ProcessLib::LocalAssemblerInterface &local_assembler, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_tables, const double t, const double dt, std::vector< GlobalVector * > const &x, std::vector< GlobalVector * > const &x_prev, int const process_id, std::vector< double > &local_b_data, std::vector< double > &local_Jac_data, ProcessLib::AbstractJacobianAssembler &jacobian_assembler, ProcessLib::Assembly::MultiMatrixElementCache &cache)
void runAssembly(std::vector< std::tuple< std::ptrdiff_t, std::reference_wrapper< ProcessLib::LocalAssemblerInterface > > > const &ids_local_assemblers, ThreadException &exception, auto local_matrix_output, auto assemble)