19#ifndef B2SOLVER_SYSTEM_H_
20#define B2SOLVER_SYSTEM_H_
22#include "b2constraint_util.H"
23#include "b2ppconfig.h"
24#include "b2solver_utils.H"
31#include "utils/b2timing.H"
34namespace b2000::solver {
36template <
typename T,
typename MATRIX_FORMAT>
40 Model*
const model, Case
const& case_, SolverUtils<T, MATRIX_FORMAT>& solver_utile,
41 RTable& solution_attr, b2linalg::Matrix<T, b2linalg::Mrectangle>& f_,
42 b2linalg::Matrix<T, b2linalg::Mrectangle>& f_reac);
44 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible> K_augm;
45 b2linalg::Matrix<T, b2linalg::Mrectangle> f_r;
46 b2linalg::Vector<T, b2linalg::Vdense> l;
47 b2linalg::Vector<T, b2linalg::Vdense> r;
48 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_L;
49 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_R;
50 b2000::b2linalg::Vector<T, b2000::b2linalg::Vdense> f_nbc_0;
56 Model*
const model, Case
const& case_, b2linalg::Vector<T, b2linalg::Vdense>& r,
57 b2linalg::Matrix<T, b2linalg::Mcompressed_col>& trans_R,
58 b2linalg::Vector<T, b2linalg::Vdense>& l,
59 b2linalg::Matrix<T, b2linalg::Mcompressed_col>& trans_L) {
60 using mrbc_t = TypedModelReductionBoundaryCondition<T>;
61 using ebc_t = TypedEssentialBoundaryCondition<T>;
65 size_t number_of_dof = model->get_domain().get_number_of_dof();
68 mrbc_t& mrbc =
dynamic_cast<mrbc_t&
>(
69 model->get_model_reduction_boundary_condition(mrbc_t::type.get_subtype(
70 "TypedModelReductionBoundaryConditionListComponent" + type_name<T>())));
71 r = b2linalg::Vector<T, b2linalg::Vdense>(number_of_dof);
72 mrbc.get_linear_value(r, trans_R);
76 dynamic_cast<ebc_t&
>(model->get_essential_boundary_condition(ebc_t::type.get_subtype(
77 "TypedEssentialBoundaryConditionListComponent" + type_name<T>())));
78 l = b2linalg::Vector<T, b2linalg::Vdense>(ebc.get_size(
true));
79 ebc.get_linear_value(l, trans_L);
82 const std::string constraint_string = case_.get_string(
"CONSTRAINT_METHOD",
"REDUCTION");
84 b2linalg::Vector<double> trans_L_scale(trans_L.size2());
85 trans_L.scale_col_to_norminf(trans_L_scale);
86 for (
size_t i = 0; i != l.size(); ++i) { l[i] *= trans_L_scale[i]; }
87 trans_L.remove_zero();
90 if (case_.get_bool(
"REMOVE_DEPENDENT_CONSTRAINTS",
true)
91 && (constraint_string ==
"LAGRANGE" || constraint_string ==
"AUGMENTED_LAGRANGE")) {
94 get_dependent_columns(trans_L, P);
97 trans_L.remove_col(P);
98 logger <<
logging::info <<
"Removed " << P.size() <<
" dependent constraints."
109template <
typename T,
typename MATRIX_FORMAT>
111 Model*
const model, b2linalg::Matrix<T, b2linalg::Mrectangle>& f_,
112 b2linalg::Matrix<T, b2linalg::Mrectangle>& f_reac,
113 b2linalg::Vector<T, b2linalg::Vdense>& f_nbc_0,
114 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>& K_nbc_0) {
115 using nbc_t = TypedNaturalBoundaryCondition<T, typename MATRIX_FORMAT::sparse_inversible>;
119 std::set<int> subcase_id_set;
120 model->get_subcase_ids(subcase_id_set);
121 std::vector<int> subcase_ids(subcase_id_set.begin(), subcase_id_set.end());
122 size_t number_of_dof = model->get_domain().get_number_of_dof();
123 SolutionStaticLinear<T>& solution =
124 dynamic_cast<SolutionStaticLinear<T>&
>(model->get_solution());
126 logger <<
logging::info <<
"Assemble the natural boundary conditions" << logging::LOGFLUSH;
127 nbc_t& nbc =
dynamic_cast<nbc_t&
>(model->get_natural_boundary_condition(nbc_t::type.get_subtype(
128 "TypedNaturalBoundaryConditionListComponent"
129 + type_name<T, typename MATRIX_FORMAT::sparse_inversible>())));
132 f_nbc_0 = b2linalg::Vector<T, b2linalg::Vdense>(number_of_dof);
133 nbc.get_linear_value(f_nbc_0, K_nbc_0);
137 for (
size_t i = 0; i != subcase_ids.size(); ++i) {
138 model->set_subcase_id(subcase_ids[i]);
139 if (subcase_ids[i] != 0) {
142 nbc.get_linear_value(
143 f_[i], b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>::null);
146 solution.set_natural_boundary_condition(f_[i]);
148 model->set_subcase_id(0);
154template <
typename T,
typename MATRIX_FORMAT>
155void assemble_from_elems(
156 Model*
const model, SolverUtils<T, MATRIX_FORMAT>& solver_utile,
157 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>
const& K_nbc_0,
158 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>& K_augm,
159 b2linalg::Matrix<T, b2linalg::Mrectangle>& f_, b2linalg::Matrix<T, b2linalg::Mrectangle>& f_r,
160 b2linalg::Vector<T, b2linalg::Vdense>& r,
161 b2linalg::Matrix<T, b2linalg::Mcompressed_col>& trans_R) {
164 Domain& domain = model->get_domain();
165 std::set<int> subcase_id_set;
166 model->get_subcase_ids(subcase_id_set);
167 std::vector<int> subcase_ids(subcase_id_set.begin(), subcase_id_set.end());
168 const size_t number_of_subcases = subcase_ids.size();
169 size_t number_of_dof = model->get_domain().get_number_of_dof();
171 b2linalg::Vector<T, b2linalg::Vdense> f_add_to_all(number_of_dof);
172 f_add_to_all.set_zero();
173 solver_utile.get_elements_values(
174 b2linalg::Matrix<T, b2linalg::Mrectangle_constref>(r), 1, 0,
true,
true, trans_R,
175 b2linalg::Vector<T, b2linalg::Vdense_constref>::null,
176 b2linalg::Vector<double, b2linalg::Vdense_constref>::null, *model, f_add_to_all, K_augm,
177 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, 0, 0, log_el);
179 if (K_nbc_0.size1() != 0) {
180 K_augm += -trans_R * K_nbc_0 * transposed(trans_R);
181 f_add_to_all += -K_nbc_0 * r;
183 for (
size_t i = 0; i != subcase_ids.size(); ++i) {
184 model->set_subcase_id(subcase_ids[i]);
185 if (subcase_ids[i] != 0 && domain.have_temperature()) {
187 b2linalg::Vector<T, b2linalg::Vdense> f_add_to_subcase(number_of_dof);
188 solver_utile.get_elements_values(
189 b2linalg::Matrix<T, b2linalg::Mrectangle_constref>(r), 1, 0,
true,
true, trans_R,
190 b2linalg::Vector<T, b2linalg::Vdense_constref>::null,
191 b2linalg::Vector<double, b2linalg::Vdense_constref>::null, *model,
193 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>::null,
194 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, 0, 0, log_el);
195 if (K_nbc_0.size1() != 0) { f_add_to_subcase += -K_nbc_0 * r; }
196 f_[i] += f_add_to_subcase;
198 f_[i] += f_add_to_all;
201 model->set_subcase_id(0);
202 f_r(b2linalg::Interval(0, trans_R.size1()), b2linalg::Interval(0, number_of_subcases)) =
207template <
typename T,
typename MATRIX_FORMAT>
208void apply_constraints(
209 Model*
const model, Case
const& case_,
210 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>& K_augm,
211 b2linalg::Matrix<T, b2linalg::Mrectangle>& f_r, b2linalg::Vector<T, b2linalg::Vdense>& l,
212 b2linalg::Vector<T, b2linalg::Vdense>& r,
213 b2linalg::Matrix<T, b2linalg::Mcompressed_col>& trans_L,
214 b2linalg::Matrix<T, b2linalg::Mcompressed_col>& trans_R) {
215 const std::string constraint_string = case_.get_string(
"CONSTRAINT_METHOD",
"REDUCTION");
216 size_t K_augm_size = trans_R.size1() + (constraint_string ==
"PENALTY" ? 0 : trans_L.size2());
217 std::set<int> subcase_id_set;
218 model->get_subcase_ids(subcase_id_set);
219 std::vector<int> subcase_ids(subcase_id_set.begin(), subcase_id_set.end());
220 const size_t number_of_subcases = subcase_ids.size();
222 if (trans_L.size2() > 0) {
223 b2linalg::Matrix<T, b2linalg::Mcompressed_col> trans_LR;
224 trans_LR = trans_R * trans_L;
225 if (constraint_string ==
"PENALTY" || constraint_string ==
"AUGMENTED_LAGRANGE") {
226 const double penalty_factor =
227 case_.get_double(
"CONSTRAINT_PENALTY", constraint_string ==
"PENALTY" ? 1e10 : 1);
228 for (
size_t i = 0; i != number_of_subcases; ++i) {
229 f_r[i](b2linalg::Interval(0, trans_R.size1())) += (trans_LR * l) * -penalty_factor;
231 K_augm += (trans_LR * transposed(trans_LR)) * penalty_factor;
233 if (constraint_string ==
"LAGRANGE" || constraint_string ==
"AUGMENTED_LAGRANGE") {
234 const double lagrange_mult_scale = case_.get_double(
"LAGRANGE_MULT_SCALE_PENALTY", 1.0);
235 for (
size_t i = 0; i != number_of_subcases; ++i) {
236 f_r[i](b2linalg::Interval(trans_R.size1(), K_augm_size)) = transposed(-trans_L) * r;
237 f_r[i](b2linalg::Interval(trans_R.size1(), K_augm_size)) -= l;
239 f_r(b2linalg::Interval(trans_R.size1(), K_augm_size),
240 b2linalg::Interval(0, number_of_subcases)) *= lagrange_mult_scale;
241 trans_LR *= lagrange_mult_scale;
242 if (!MATRIX_FORMAT::symmetric) {
244 b2linalg::Interval(0, trans_R.size1()),
245 b2linalg::Interval(trans_R.size1(), K_augm_size)) += trans_LR;
247 b2linalg::Matrix<T, b2linalg::Mcompressed_col> LR = transposed(trans_LR);
249 b2linalg::Interval(trans_R.size1(), K_augm_size),
250 b2linalg::Interval(0, trans_R.size1())) += LR;
257template <
typename T,
typename MATRIX_FORMAT>
258void handle_singularities(
259 Model*
const model, Case
const& case_,
260 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>& K_augm,
261 b2linalg::Matrix<T, b2linalg::Mcompressed_col>& trans_R) {
262 SolutionStaticLinear<T>& solution =
263 dynamic_cast<SolutionStaticLinear<T>&
>(model->get_solution());
264 const bool autospc = case_.get_bool(
"AUTOSPC",
false);
266 std::set<size_t> zero_columns_r;
267 for (
size_t i = 0; i != K_augm.size1(); ++i) {
268 if (K_augm(i, i) == T(0)) {
269 bool all_zero =
true;
270 for (
size_t j = 0; all_zero && j != K_augm.size2(); ++j) {
271 if (K_augm(i, j) != T(0)) { all_zero =
false; }
274 zero_columns_r.insert(i);
275 if (autospc) { K_augm(i, i) = 1.; }
280 if (!zero_columns_r.empty()) {
281 b2linalg::Matrix<T, b2linalg::Mrectangle> nks_r;
282 nks_r.resize(trans_R.size1(), 1);
284 for (
auto i : zero_columns_r) { nks_r(i, 0) = T(1); }
285 b2linalg::Matrix<T, b2linalg::Mrectangle> nks;
286 nks = transposed(trans_R)
287 * nks_r(b2linalg::Interval(0, trans_R.size1()), b2linalg::Interval(0, nks_r.size2()));
288 for (
size_t i = 0; i != nks.size1(); ++i) { nks(i, 0) = (nks(i, 0) != T(0) ? T(1) : T(0)); }
289 solution.set_system_null_space(nks,
false,
"NS_STRUCTURE");
294template <
typename T,
typename MATRIX_FORMAT>
296 Model*
const model, Case
const& case_, SolverUtils<T, MATRIX_FORMAT>& solver_utile,
297 RTable& solution_attr, b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>& K_augm,
298 b2linalg::Matrix<T, b2linalg::Mrectangle>& f_, b2linalg::Matrix<T, b2linalg::Mrectangle>& f_r,
299 b2linalg::Matrix<T, b2linalg::Mrectangle>& f_reac, b2linalg::Vector<T, b2linalg::Vdense>& l,
300 b2linalg::Vector<T, b2linalg::Vdense>& r, b2linalg::Vector<T, b2linalg::Vdense>& f_nbc_0,
301 b2linalg::Matrix<T, b2linalg::Mcompressed_col>& trans_L,
302 b2linalg::Matrix<T, b2linalg::Mcompressed_col>& trans_R) {
304 auto time_nbc =
obtain_timer(
"static_linear_analysis.nbc");
305 auto time_elements =
obtain_timer(
"static_linear_analysis.elements");
307 const std::string constraint_string = case_.get_string(
"CONSTRAINT_METHOD",
"REDUCTION");
308 Domain& domain = model->get_domain();
309 std::set<int> subcase_id_set;
310 model->get_subcase_ids(subcase_id_set);
311 std::vector<int> subcase_ids(subcase_id_set.begin(), subcase_id_set.end());
312 const size_t number_of_subcases = subcase_ids.size();
314 bc_elimination<T>(model, case_, r, trans_R, l, trans_L);
321 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible> K_nbc_0;
322 (*time_nbc).second.start();
323 apply_nbcs<T, MATRIX_FORMAT>(model, f_, f_reac, f_nbc_0, K_nbc_0);
324 (*time_nbc).second.stop();
325 solution_attr.set(
"ELAPSED_TIME_NBC", (*time_nbc).second.duration());
328 logger <<
logging::info <<
"Element matrix assembly" << logging::LOGFLUSH;
329 (*time_elements).second.start();
331 size_t K_augm_size = trans_R.size1() + (constraint_string ==
"PENALTY" ? 0 : trans_L.size2());
332 K_augm = b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>(
333 K_augm_size, domain.get_dof_connectivity_type(), case_);
334 f_r = b2linalg::Matrix<T, b2linalg::Mrectangle>(K_augm_size, number_of_subcases);
335 assemble_from_elems<T, MATRIX_FORMAT>(
336 model, solver_utile, K_nbc_0, K_augm, f_, f_r, r, trans_R);
339 apply_constraints<T, MATRIX_FORMAT>(model, case_, K_augm, f_r, l, r, trans_L, trans_R);
343 << logging::DBName(
"D_VALUE_D_DOF.GLOB", 0, 0, case_.get_id()) << K_augm
344 << logging::LOGFLUSH;
345 logger <<
logging::data <<
"value " << logging::DBName(
"VALUE.GLOB", 0, 0, case_.get_id())
346 << f_r << logging::LOGFLUSH;
348 (*time_elements).second.stop();
349 solution_attr.set(
"ELAPSED_TIME_ELEMENTS", (*time_elements).second.duration());
353template <
typename T,
typename MATRIX_FORMAT>
354void SolverSystem<T, MATRIX_FORMAT>::assemble(
355 Model*
const model, Case
const& case_, SolverUtils<T, MATRIX_FORMAT>& solver_utile,
356 RTable& solution_attr, b2linalg::Matrix<T, b2linalg::Mrectangle>& f_,
357 b2linalg::Matrix<T, b2linalg::Mrectangle>& f_reac) {
358 assemble_system<T, MATRIX_FORMAT>(
359 model, case_, solver_utile, solution_attr, K_augm, f_, f_r, f_reac, l, r, f_nbc_0,
Logger & get_logger(const std::string &logger_name="")
Definition b2logging.H:829
timer_map_t::iterator obtain_timer(std::string name)
Definition b2timing.H:139