21#ifndef B2STATIC_LINEAR_SOLVER_H_
22#define B2STATIC_LINEAR_SOLVER_H_
24#include "b2constraint_util.H"
25#include "b2ppconfig.h"
26#include "b2solver_system.H"
27#include "b2solver_utils.H"
30#include "model/b2element.H"
35#include "utils/b2timing.H"
38namespace b2000::solver {
69template <
typename T,
typename MATRIX_FORMAT>
79 if (case_list.get_number_of_case() == 1) {
80 case_iterator_ = case_list.get_case_iterator();
81 solve_on_case(*case_iterator_->next());
85 case_iterator_ = case_list.get_case_iterator();
87 auto c = case_iterator_->next();
88 if (c ==
nullptr) {
break; }
102 SolverUtils<T, MATRIX_FORMAT> solver_utile;
103 b2linalg::Matrix<T, b2linalg::Mrectangle> f_;
104 b2linalg::Matrix<T, b2linalg::Mrectangle> f_reac_;
105 SolverSystem<T, MATRIX_FORMAT> static_lin_sys;
109template <
typename T,
typename MATRIX_FORMAT>
110typename StaticLinearSolver<T, MATRIX_FORMAT>::type_t StaticLinearSolver<T, MATRIX_FORMAT>::type(
111 "StaticLinearSolver", type_name<T, MATRIX_FORMAT>(),
StringList(
"LINEAR"), module,
174template <
typename T,
typename MATRIX_FORMAT>
176 logging::Logger& logger = logging::get_logger(
"solver.static_linear");
178 auto time_analysis = obtain_timer(
"static_linear_analysis");
179 auto time_sysresolve = obtain_timer(
"static_linear_analysis.sysresolve");
181 (*time_analysis).second.start();
184 logging::Logger& log_el = logging::get_logger(
"elementary_matrix");
186 if (model_ ==
nullptr) { Exception() <<
THROW; }
188 const std::string constraint_string = case_.get_string(
"CONSTRAINT_METHOD",
"REDUCTION");
190 model_->set_case(case_);
192 logger << logging::info <<
"Start static linear solver for case " << case_.get_id()
193 << logging::LOGFLUSH;
195 Domain& domain = model_->get_domain();
196 size_t number_of_dof = domain.get_number_of_dof();
197 SolutionStaticLinear<T>& solution =
198 dynamic_cast<SolutionStaticLinear<T>&
>(model_->get_solution());
200 typename SolutionStaticLinear<T>::gradient_container gc = solution.get_gradient_container();
202 const bool compute_rcfo =
203 solution.compute_constraint_value()
204 && (constraint_string ==
"REDUCTION" || case_.get_bool(
"GRADIENTS_ONLY",
false));
207 std::set<int> subcase_id_set;
208 model_->get_subcase_ids(subcase_id_set);
209 std::vector<int> subcase_ids(subcase_id_set.begin(), subcase_id_set.end());
210 const size_t number_of_subcases = subcase_ids.size();
212 RTable solution_attr;
213 f_.resize(number_of_dof, number_of_subcases);
215 if (!case_.get_bool(
"GRADIENTS_ONLY",
false)) {
216 static_lin_sys.assemble(model_, case_, solver_utile, solution_attr, f_, f_reac_);
218 logger.LOG(logging::info,
"Resolve the linear problem");
219 (*time_sysresolve).second.start();
225 handle_singularities<T, MATRIX_FORMAT>(
226 model_, case_, static_lin_sys.K_augm, static_lin_sys.trans_R);
231 const int nbnsv = case_.get_int(
"COMPUTE_NULL_SPACE_VECTOR", 0);
232 b2linalg::Matrix<T, b2linalg::Mrectangle> nks_r;
233 static_lin_sys.K_augm.remove_zero();
234 b2linalg::SingularMatrixError ee;
235 bool is_singular =
false;
237 static_lin_sys.f_r = inverse(static_lin_sys.K_augm, nks_r, nbnsv) * static_lin_sys.f_r;
238 }
catch (b2linalg::SingularMatrixError& e) {
241 if (!e.singular_dofs.empty()) {
242 if (nks_r.size2() == 0) {
243 nks_r.resize(static_lin_sys.trans_R.size1(), 1);
246 for (
auto i : e.singular_dofs) {
247 assert(i < nks_r.size1());
248 for (
size_t j = 0; j != nks_r.size2(); ++j) { nks_r(i, j) = T(1); }
252 (*time_sysresolve).second.stop();
253 solution_attr.set(
"ELAPSED_TIME_SYSTEM_RESOLUTION", (*time_sysresolve).second.duration());
254 if (nks_r.size2() != 0) {
255 b2linalg::Matrix<T, b2linalg::Mrectangle> nks;
256 nks = transposed(static_lin_sys.trans_R)
258 b2linalg::Interval(0, static_lin_sys.trans_R.size1()),
259 b2linalg::Interval(0, nks_r.size2()));
260 solution.set_system_null_space(nks);
262 if (is_singular) { ee <<
THROW; }
265 f_ = transposed(static_lin_sys.trans_R)
266 * static_lin_sys.f_r(
267 b2linalg::Interval(0, static_lin_sys.trans_R.size1()),
268 b2linalg::Interval(0, number_of_subcases));
269 for (
size_t i = 0; i != number_of_subcases; ++i) {
270 f_[i] += static_lin_sys.r;
271 solution.set_subcase_id(subcase_ids[i]);
272 solution.set_dof(f_[i]);
274 solution.set_subcase_id(0);
277 if (solution.compute_constraint_value() && !compute_rcfo) {
278 for (
size_t i = 0; i != number_of_subcases; ++i) {
279 b2linalg::Vector<T, b2linalg::Vdense> ll;
280 ll = static_lin_sys.l;
282 if (constraint_string ==
"PENALTY" || constraint_string ==
"AUGMENTED_LAGRANGE") {
283 ll += transposed(static_lin_sys.trans_L) * f_[i];
284 const double penalty_factor = case_.get_double(
285 "CONSTRAINT_PENALTY", constraint_string ==
"PENALTY" ? 1e10 : 1);
286 ll *= -penalty_factor;
290 if (constraint_string ==
"LAGRANGE" || constraint_string ==
"AUGMENTED_LAGRANGE") {
291 const double lagrange_mult_scale =
292 case_.get_double(
"LAGRANGE_MULT_SCALE_PENALTY", 1.0);
293 ll += T(-lagrange_mult_scale)
294 * static_lin_sys.f_r[i](b2linalg::Interval(
295 static_lin_sys.trans_R.size1(), static_lin_sys.f_r[i].size()));
297 if (case_.get_bool(
"RCFO_ONLY_SPC",
false)) {
298 for (
size_t j = 0; j != static_lin_sys.trans_L.size2(); ++j) {
299 if (static_lin_sys.trans_L.get_nb_nonzero(j) != 1) { ll[j] = 0; }
302 f_reac_[i] = static_lin_sys.trans_L * ll;
303 solution.set_subcase_id(subcase_ids[i]);
304 solution.set_constraint_value(f_reac_[i]);
306 solution.set_subcase_id(0);
311 for (
size_t i = 0; i != subcase_ids.size(); ++i) {
312 solution.set_subcase_id(subcase_ids[i]);
313 solution.get_dof(f_[i]);
315 solution.set_subcase_id(0);
318 nbc_t& nbc =
dynamic_cast<nbc_t&
>(
319 model_->get_natural_boundary_condition(nbc_t::type.get_subtype(
320 "TypedNaturalBoundaryConditionListComponent"
321 + type_name<T, typename MATRIX_FORMAT::sparse_inversible>())));
323 b2linalg::Vector<T, b2linalg::Vdense> f_nbc_0(number_of_dof);
324 nbc.get_linear_value(
325 f_nbc_0, b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>::null);
328 for (
size_t i = 0; i != subcase_ids.size(); ++i) {
329 if (subcase_ids[i] != 0) {
330 nbc.set_subcase_id(subcase_ids[i]);
331 nbc.get_linear_value(
333 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>::null);
336 solution.set_subcase_id(subcase_ids[i]);
337 solution.set_natural_boundary_condition(f_[i]);
339 nbc.set_subcase_id(0);
340 solution.set_subcase_id(0);
347 if (gc.get() != 0 || compute_rcfo) {
348 logger.LOG(logging::info,
"Compute gradients and reaction forces");
350 for (
size_t i = 0; i != number_of_subcases; ++i) {
351 domain.set_dof(b2linalg::Matrix<T, b2linalg::Mrectangle_constref>(f_[i]));
353 model_->set_subcase_id(subcase_ids[i]);
355 Domain::element_iterator ii = domain.get_element_iterator();
356 b2linalg::Index index;
357 solver_utile.get_elements_values(
358 b2linalg::Matrix<T, b2linalg::Mrectangle_constref>(f_[i]), 1, 0,
true,
true,
359 b2linalg::Matrix<T, b2linalg::Mcompressed_col>::null,
360 b2linalg::Vector<T, b2linalg::Vdense_constref>::null,
361 b2linalg::Vector<double, b2linalg::Vdense_constref>::null, *model_,
362 compute_rcfo ? f_reac_[i] : b2linalg::Vector<T, b2linalg::Vdense>::null,
363 b2linalg::Matrix<T, typename MATRIX_FORMAT::sparse_inversible>::null,
364 b2linalg::Vector<T, b2linalg::Vdense_ref>::null, gc.get(), 0, log_el);
366 if (compute_rcfo) { solution.set_constraint_value(f_reac_[i]); }
368 model_->set_subcase_id(0);
370 (*time_analysis).second.stop();
371 solution_attr.set(
"ELAPSED_TIME_ANALYSIS", (*time_analysis).second.duration());
372 solution.terminate_case(
true, solution_attr);
375 logger.LOG(logging::info,
"End of static linear solver");
376 case_.warn_on_non_used_key();
#define THROW
Definition b2exception.H:198
virtual CaseList & get_case_list()=0
Definition b2object.H:415
A Solver instance executes an FE analysis. It is created and initialized by the Model instance and,...
Definition b2solver.H:50
Case * case_
This also.
Definition b2solver.H:93
Model * model_
Definition b2solver.H:91
Definition b2boundary_condition.H:198
Definition b2boundary_condition.H:302
Definition b2boundary_condition.H:81
Definition b2static_linear_solver.H:70
void solve() override
This function is usually called by the Model instance.
Definition b2static_linear_solver.H:77
bool solve_iteration() override
This function is called by the Solver instance itself.
Definition b2static_linear_solver.H:94