38 template <
class CONTAINER>
class distro 43 void build_distro(gmm::abstract_matrix)
45 for(
size_type thread = 1; thread < num_threads(); thread++)
47 gmm::resize(distributed(thread), gmm::mat_nrows(original),gmm::mat_ncols(original));
51 void build_distro(gmm::abstract_vector)
54 for(
size_type thread = 1; thread < num_threads(); thread++)
56 gmm::resize(distributed(thread), gmm::vect_size(original));
60 bool not_multithreaded()
const {
return num_threads() == 1; }
64 distro(CONTAINER& c) : original(c)
66 if (not_multithreaded())
return;
67 build_distro(
typename gmm::linalg_traits<CONTAINER>::linalg_type());
72 if (not_multithreaded() || this_thread() == 0)
return original;
73 else return distributed(this_thread());
78 if (not_multithreaded())
return;
80 GMM_ASSERT1(!me_is_multithreaded_now(),
81 "List accumulation should not run in parallel");
83 for(
size_type thread = 1; thread < num_threads(); thread++)
85 gmm::add(distributed(thread), original);
90 model::model(
bool comp_version) {
91 init(); complex_version = comp_version;
92 is_linear_ = is_symmetric_ = is_coercive_ =
true;
94 time_integration = 0; init_step =
false; time_step = scalar_type(1);
95 add_interpolate_transformation
99 void model::var_description::set_size() {
103 complex_value.resize(n_iter);
105 real_value.resize(n_iter);
106 v_num_var_iter.resize(n_iter);
107 v_num_iter.resize(n_iter);
108 size_type s = is_fem_dofs ? passociated_mf()->nb_dof()
110 (pim_data->nb_filtered_index() * pim_data->nb_tensor_elem()) : 1);
114 complex_value[i].resize(s);
116 real_value[i].resize(s);
117 if (is_affine_dependent) {
119 affine_complex_value.resize(s);
121 affine_real_value.resize(s);
125 size_type model::var_description::add_temporary(gmm::uint64_type id_num) {
127 for (; nit < n_iter + n_temp_iter ; ++nit)
128 if (v_num_var_iter[nit] == id_num)
break;
129 if (nit >= n_iter + n_temp_iter) {
131 v_num_var_iter.resize(nit+1);
132 v_num_var_iter[nit] = id_num;
133 v_num_iter.resize(nit+1);
137 complex_value.resize(n_iter + n_temp_iter);
138 complex_value[nit].resize(s);
141 real_value.resize(n_iter + n_temp_iter);
142 real_value[nit].resize(s);
148 void model::var_description::clear_temporaries() {
152 complex_value.resize(n_iter);
154 real_value.resize(n_iter);
157 bool model::check_name_validity(
const std::string &name,
bool assert)
const {
158 VAR_SET::const_iterator it = variables.find(name);
159 if (it != variables.end()) {
160 GMM_ASSERT1(!assert,
"Variable " << name <<
" already exists");
164 if (variable_groups.find(name) != variable_groups.end()) {
166 name <<
" corresponds to an already existing group of " 171 if (macro_exists(name)) {
173 name <<
" corresponds to an already existing macro");
177 if (name.compare(
"X") == 0) {
178 GMM_ASSERT1(!assert,
"X is a reserved keyword of the generic " 179 "assembly language");
183 int ga_valid = ga_check_name_validity(name);
185 GMM_ASSERT1(!assert,
"Invalid variable name, corresponds to an " 186 "operator or function name of the generic assembly language");
191 GMM_ASSERT1(!assert,
"Invalid variable name having a reserved " 192 "prefix used by the generic assembly language");
197 std::string org_name = sup_previous_and_dot_to_varname(name);
198 if (org_name.size() < name.size() &&
199 variables.find(org_name) != variables.end()) {
201 "Dot and Previous are reserved prefix used for time " 202 "integration schemes");
208 if (name.size() == 0) valid =
false;
210 if (!isalpha(name[0])) valid =
false;
211 for (
size_type i = 1; i < name.size(); ++i)
212 if (!(isalnum(name[i]) || name[i] ==
'_')) valid =
false;
214 GMM_ASSERT1(!assert || valid,
215 "Illegal variable name : \"" << name <<
"\"");
220 std::string res_name = name;
221 bool valid = check_name_validity(res_name,
false);
222 for (
size_type i = 2; !valid && i < 50; ++i) {
224 m << name <<
'_' << i;
226 valid = check_name_validity(res_name,
false);
228 for (
size_type i = 2; !valid && i < 1000; ++i) {
230 m <<
"new_" << name <<
'_' << i;
232 valid = check_name_validity(res_name,
false);
234 GMM_ASSERT1(valid,
"Illegal variable name: " << name);
239 model::VAR_SET::const_iterator
240 model::find_variable(
const std::string &name)
const {
241 VAR_SET::const_iterator it = variables.find(name);
242 GMM_ASSERT1(it != variables.end(),
"Undefined variable " << name);
246 std::string sup_previous_and_dot_to_varname(std::string v) {
247 if (!(v.compare(0, 8,
"Previous")) && (v[8] ==
'_' || v[9] ==
'_')) {
248 v = v.substr((v[8] ==
'_') ? 9 : 10);
250 if (!(v.compare(0, 3,
"Dot")) && (v[3] ==
'_' || v[4] ==
'_')) {
251 v = v.substr((v[3] ==
'_') ? 4 : 5);
258 return name.substr(0, PREFIX_OLD_LENGTH) ==
PREFIX_OLD;
262 return is_old(name) ? name.substr(PREFIX_OLD_LENGTH) : name;
265 bool model::is_disabled_variable(
const std::string &name)
const {
266 if (
is_old(name))
return false;
267 VAR_SET::const_iterator it = find_variable(name);
268 if (!(it->second.is_variable))
return false;
269 if (it->second.is_affine_dependent)
270 it = variables.find(it->second.org_name);
271 return it->second.is_disabled;
275 if (
is_old(name))
return true;
276 VAR_SET::const_iterator it = find_variable(name);
277 if (it->second.is_affine_dependent)
278 it = variables.find(it->second.org_name);
279 return (!(it->second.is_variable) || it->second.is_disabled);
283 if (
is_old(name))
return true;
284 VAR_SET::const_iterator it = find_variable(name);
285 return (!(it->second.is_variable));
288 bool model::is_affine_dependent_variable(
const std::string &name)
const {
289 if (
is_old(name))
return false;
290 VAR_SET::const_iterator it = find_variable(name);
291 return (it->second.is_affine_dependent);
294 const std::string &model::org_variable(
const std::string &name)
const {
295 VAR_SET::const_iterator it = variables.find(name);
296 GMM_ASSERT1(is_affine_dependent_variable(name),
297 "For affine dependent variables only");
298 return (it->second.org_name);
302 model::factor_of_variable(
const std::string &name)
const {
303 VAR_SET::const_iterator it = find_variable(name);
304 return (it->second.alpha);
307 void model::set_factor_of_variable(
const std::string &name,
309 VAR_SET::iterator it = variables.find(name);
310 GMM_ASSERT1(it != variables.end(),
"Undefined variable " << name);
311 if (it->second.alpha != a) {
312 it->second.alpha = a;
313 for (
auto &v_num : it->second.v_num_data) v_num = act_counter();
317 bool model::is_im_data(
const std::string &name)
const {
319 return (it->second.pim_data != 0);
323 model::pim_data_of_variable(
const std::string &name)
const {
325 return it->second.pim_data;
328 const gmm::uint64_type &
329 model::version_number_of_data_variable(
const std::string &name,
size_type niter)
const {
330 VAR_SET::const_iterator it = find_variable(name);
331 if (niter ==
size_type(-1)) niter = it->second.default_iter;
332 return it->second.v_num_data[niter];
337 if (act_size_to_be_done) actualize_sizes();
338 return (complex_version) ? gmm::vect_size(crhs) : gmm::vect_size(rrhs);
341 void model::resize_global_system()
const {
344 for (
auto && v : variables) {
345 if (v.second.is_variable && v.second.is_disabled)
346 v.second.I = gmm::sub_interval(0,0);
347 if (v.second.is_variable && !(v.second.is_affine_dependent)
348 && !(v.second.is_disabled)) {
349 v.second.I = gmm::sub_interval(tot_size, v.second.size());
350 tot_size += v.second.size();
354 for (
auto &&v : variables)
355 if (v.second.is_affine_dependent) {
356 v.second.I = variables.find(v.second.org_name)->second.I;
360 if (complex_version) {
361 gmm::resize(cTM, tot_size, tot_size);
362 gmm::resize(crhs, tot_size);
365 gmm::resize(rTM, tot_size, tot_size);
366 gmm::resize(rrhs, tot_size);
369 for (dal::bv_visitor ib(valid_bricks); !ib.finished(); ++ib)
370 for (
const term_description &term : bricks[ib].tlist)
371 if (term.is_global) {
372 bricks[ib].terms_to_be_computed =
true;
377 void model::actualize_sizes()
const {
379 bool actualized =
false;
380 getfem::local_guard lock = locks_.get_lock();
381 if (actualized)
return;
383 act_size_to_be_done =
false;
385 std::map<std::string, std::vector<std::string> > multipliers;
386 std::set<std::string> tobedone;
398 for (dal::bv_visitor ib(valid_bricks); !ib.finished(); ++ib)
399 bricks[ib].terms_to_be_computed =
true;
401 for (
auto &&v : variables) {
402 const std::string &vname = v.first;
403 var_description &vdescr = v.second;
404 if (vdescr.is_fem_dofs && !(vdescr.is_affine_dependent)) {
405 if ((vdescr.filter & VDESCRFILTER_CTERM)
406 || (vdescr.filter & VDESCRFILTER_INFSUP)) {
407 VAR_SET::iterator vfilt = variables.find(vdescr.filter_var);
408 GMM_ASSERT1(vfilt != variables.end(),
"The primal variable of the" 409 " multiplier does not exist : " << vdescr.filter_var);
410 GMM_ASSERT1(vfilt->second.is_fem_dofs,
"The primal variable of " 411 "the multiplier is not a fem variable");
412 multipliers[vdescr.filter_var].push_back(vname);
413 if (vdescr.v_num < vdescr.mf->version_number() ||
414 vdescr.v_num < vfilt->second.mf->version_number()) {
415 tobedone.insert(vdescr.filter_var);
418 switch (vdescr.filter) {
419 case VDESCRFILTER_NO:
420 if (vdescr.v_num < vdescr.mf->version_number()) {
422 vdescr.v_num = act_counter();
425 case VDESCRFILTER_REGION:
426 if (vdescr.v_num < vdescr.mf->version_number()) {
428 = vdescr.mf->dof_on_region(vdescr.m_region);
429 vdescr.partial_mf->adapt(dor);
431 vdescr.v_num = act_counter();
438 if (vdescr.pim_data != 0
439 && vdescr.v_num < vdescr.pim_data->version_number()) {
442 vdescr.v_num = act_counter();
446 for (
auto &&v : variables) {
447 var_description &vdescr = v.second;
448 if (vdescr.is_fem_dofs && !(vdescr.is_affine_dependent) &&
449 ((vdescr.filter & VDESCRFILTER_CTERM)
450 || (vdescr.filter & VDESCRFILTER_INFSUP))) {
451 if (tobedone.count(vdescr.filter_var)) {
456 dal::bit_vector alldof; alldof.add(0, vdescr.mf->nb_dof());
457 vdescr.partial_mf->adapt(alldof);
459 vdescr.v_num = act_counter();
464 resize_global_system();
466 for (
const std::string &vname : tobedone) {
473 const std::vector<std::string> &mults = multipliers[vname];
474 const var_description &vdescr = variables.find(vname)->second;
476 gmm::col_matrix< gmm::rsvector<scalar_type> > MGLOB;
477 if (mults.size() > 1) {
479 for (
const std::string &mult : mults)
480 s += variables.find(mult)->second.mf->nb_dof();
481 gmm::resize(MGLOB, vdescr.mf->nb_dof(), s);
484 std::set<size_type> glob_columns;
485 for (
const std::string &multname : mults) {
486 var_description &multdescr = variables.find(multname)->second;
492 gmm::col_matrix< gmm::rsvector<scalar_type> >
493 MM(vdescr.associated_mf().nb_dof(), multdescr.mf->nb_dof());
494 bool termadded =
false;
496 if (multdescr.filter & VDESCRFILTER_CTERM) {
498 for (dal::bv_visitor ib(valid_bricks); !ib.finished(); ++ib) {
499 const brick_description &brick = bricks[ib];
501 bool cplx = is_complex() && brick.pbr->is_complex();
503 if (brick.tlist.size() == 0) {
504 bool varc =
false, multc =
false;
505 for (
const std::string &var : brick.vlist) {
506 if (multname.compare(var) == 0) multc =
true;
507 if (vname.compare(var) == 0) varc =
true;
510 GMM_ASSERT1(!cplx,
"Sorry, not taken into account");
511 generic_expressions.clear();
512 brick.terms_to_be_computed =
true;
513 update_brick(ib, BUILD_MATRIX);
514 if (generic_expressions.size()) {
515 GMM_TRACE2(
"Generic assembly for actualize sizes");
520 open_mp_is_running_properly check;
522 #pragma omp parallel default(shared) 526 ga_workspace workspace(*
this);
527 for (
const auto &ge : generic_expressions)
528 workspace.add_expression(ge.expr, ge.mim, ge.region);
529 workspace.set_assembled_matrix(distro_rTM);
530 workspace.assembly(2);
536 (gmm::sub_matrix(rTM, vdescr.I, multdescr.I), MM);
537 gmm::add(gmm::transposed
538 (gmm::sub_matrix(rTM, multdescr.I,
546 for (
size_type j = 0; j < brick.tlist.size(); ++j) {
547 const term_description &term = brick.tlist[j];
549 if (term.is_matrix_term) {
550 if (term.is_global) {
551 bool varc =
false, multc =
false;
552 for (
const std::string var : brick.vlist) {
553 if (multname.compare(var) == 0) multc =
true;
554 if (vname.compare(var) == 0) varc =
true;
557 GMM_ASSERT1(!cplx,
"Sorry, not taken into account");
558 generic_expressions.clear();
560 brick.terms_to_be_computed =
true;
561 update_brick(ib, BUILD_MATRIX);
564 gmm::add(gmm::sub_matrix(brick.rmatlist[j],
565 multdescr.I, vdescr.I),
567 gmm::add(gmm::transposed(gmm::sub_matrix
569 vdescr.I, multdescr.I)),
573 }
else if (multname.compare(term.var1) == 0 &&
574 vname.compare(term.var2) == 0) {
576 brick.terms_to_be_computed =
true;
577 update_brick(ib, BUILD_MATRIX);
582 (gmm::transposed(gmm::real_part(brick.cmatlist[j])), MM);
584 gmm::add(gmm::transposed(brick.rmatlist[j]), MM);
587 }
else if (multname.compare(term.var2) == 0 &&
588 vname.compare(term.var1) == 0) {
590 brick.terms_to_be_computed =
true;
591 update_brick(ib, BUILD_MATRIX);
595 gmm::add(gmm::real_part(brick.cmatlist[j]), MM);
597 gmm::add(brick.rmatlist[j], MM);
605 GMM_WARNING1(
"No term found to filter multiplier " << multname
606 <<
". Variable is cancelled");
607 }
else if (multdescr.filter & VDESCRFILTER_INFSUP) {
609 multdescr.mim->linked_mesh().intersect_with_mpi_region(rg);
611 *(multdescr.mf), rg);
614 MPI_SUM_SPARSE_MATRIX(MM);
619 std::set<size_type> columns;
620 gmm::range_basis(MM, columns);
621 if (columns.size() == 0)
622 GMM_WARNING1(
"Empty basis found for multiplier " << multname);
624 if (mults.size() > 1) {
625 gmm::copy(MM, gmm::sub_matrix
627 gmm::sub_interval(0, vdescr.associated_mf().nb_dof()),
628 gmm::sub_interval(s, multdescr.mf->nb_dof())));
630 glob_columns.insert(s + icol);
631 s += multdescr.mf->nb_dof();
633 dal::bit_vector kept;
636 if (multdescr.filter & VDESCRFILTER_REGION)
637 kept &= multdescr.mf->dof_on_region(multdescr.m_region);
638 multdescr.partial_mf->adapt(kept);
639 multdescr.set_size();
640 multdescr.v_num = act_counter();
649 if (mults.size() > 1) {
650 gmm::range_basis(MGLOB, glob_columns, 1E-12, gmm::col_major(),
true);
659 for (
const std::string &multname : mults) {
660 var_description &multdescr = variables.find(multname)->second;
661 dal::bit_vector kept;
662 size_type nbdof = multdescr.mf->nb_dof();
663 for (
const size_type &icol : glob_columns)
664 if (icol >= s && icol < s + nbdof) kept.add(icol-s);
665 if (multdescr.filter & VDESCRFILTER_REGION)
666 kept &= multdescr.mf->dof_on_region(multdescr.m_region);
667 multdescr.partial_mf->adapt(kept);
668 multdescr.set_size();
669 multdescr.v_num = act_counter();
670 s += multdescr.mf->nb_dof();
679 resize_global_system();
691 if (variables.size() == 0)
692 ost <<
"Model with no variable nor data" << endl;
694 ost <<
"List of model variables and data:" << endl;
695 for (
auto it = variables.begin(); it != variables.end(); ++it) {
696 if (it->second.is_variable) ost <<
"Variable ";
698 ost << std::setw(30) << std::left << it->first;
699 if (it->second.n_iter == 1)
702 ost << std::setw(2) << std::right << it->second.n_iter
704 if (it->second.is_fem_dofs) ost <<
"fem dependant ";
705 else ost <<
"constant size ";
707 ost << std::setw(8) << std::right << si;
708 if (is_complex()) ost <<
" complex";
709 ost <<
" double" << ((si > 1) ?
"s." :
".");
710 if (it->second.is_variable &&
711 is_disabled_variable(it->first)) ost <<
"\t (disabled)";
713 if (it->second.pim_data != 0) ost <<
"\t (is im_data)";
714 if (it->second.is_affine_dependent) ost <<
"\t (is affine dependent)";
717 for (
auto it = variable_groups.begin();
718 it != variable_groups.end(); ++it) {
719 ost <<
"Variable group " << std::setw(30) << std::left
721 if (it->second.size()) {
722 auto it2 = it->second.begin();
723 ost <<
" " << *it2; ++it2;
724 for (; it2 != it->second.end(); ++it2) ost <<
", " << *it2;
726 }
else ost <<
" empty" << endl;
731 void model::listresiduals(std::ostream &ost)
const {
732 if (variables.size() == 0)
733 ost <<
"Model with no variable nor data" << endl;
736 for (VAR_SET::const_iterator it = variables.begin();
737 it != variables.end(); ++it) {
738 if (it->second.is_variable) {
739 const gmm::sub_interval &II = interval_of_variable(it->first);
740 scalar_type res = gmm::vect_norm2(gmm::sub_vector(rrhs, II));
741 if (!firstvar) cout <<
", ";
742 ost <<
"res_" << it->first <<
"= " << std::setw(11) << res;
752 check_name_validity(name);
753 variables[name] = var_description(
true, is_complex(),
false, niter);
754 GMM_ASSERT1(size,
"Variable of null size are not allowed");
755 variables[name].qdims[0] = size;
756 act_size_to_be_done =
true;
757 variables[name].set_size();
761 const bgeot::multi_index &sizes,
763 check_name_validity(name);
764 variables[name] = var_description(
true, is_complex(),
false, niter,
767 act_size_to_be_done =
true;
768 variables[name].set_size();
774 GMM_ASSERT1(!(variables[name].is_fem_dofs),
775 "Cannot explicitly resize a fem variable or data");
776 GMM_ASSERT1(variables[name].pim_data == 0,
777 "Cannot explicitly resize an im data");
778 GMM_ASSERT1(size,
"Variable of null size are not allowed");
779 variables[name].qdims.resize(1);
780 variables[name].qdims[0] = size;
781 variables[name].set_size();
785 const bgeot::multi_index &sizes) {
786 GMM_ASSERT1(!(variables[name].is_fem_dofs),
787 "Cannot explicitly resize a fem variable or data");
788 GMM_ASSERT1(variables[name].pim_data == 0,
789 "Cannot explicitly resize an im data");
790 variables[name].qdims = sizes;
791 variables[name].set_size();
797 check_name_validity(name);
798 variables[name] = var_description(
false, is_complex(),
false, niter);
799 GMM_ASSERT1(size,
"Data of null size are not allowed");
800 variables[name].qdims[0] = size;
801 variables[name].set_size();
805 const bgeot::multi_index &sizes,
807 check_name_validity(name);
808 variables[name] = var_description(
false, is_complex(),
false, niter);
809 variables[name].qdims = sizes;
810 GMM_ASSERT1(variables[name].qdim(),
"Data of null size are not allowed");
811 variables[name].set_size();
815 const base_matrix &M) {
816 this->add_fixed_size_data(name, bgeot::multi_index(gmm::mat_nrows(M),
818 GMM_ASSERT1(!(this->is_complex()),
"Sorry, complex version to be done");
819 gmm::copy(M.as_vector(), this->set_real_variable(name));
823 const base_complex_matrix &M) {
824 this->add_fixed_size_data(name, bgeot::multi_index(gmm::mat_nrows(M),
826 GMM_ASSERT1(!(this->is_complex()),
"Sorry, complex version to be done");
827 gmm::copy(M.as_vector(), this->set_complex_variable(name));
831 const base_tensor &t) {
832 this->add_fixed_size_data(name, t.sizes(), 1);
833 GMM_ASSERT1(!(this->is_complex()),
"Sorry, complex version to be done");
834 gmm::copy(t.as_vector(), this->set_real_variable(name));
838 const base_complex_tensor &t) {
839 this->add_fixed_size_data(name, t.sizes(), 1);
840 GMM_ASSERT1(!(this->is_complex()),
"Sorry, complex version to be done");
841 gmm::copy(t.as_vector(), this->set_complex_variable(name));
846 check_name_validity(name);
847 variables[name] = var_description(
false, is_complex(),
false, niter);
848 variables[name].pim_data = &im_data;
849 variables[name].set_size();
850 add_dependency(im_data);
855 check_name_validity(name);
856 variables[name] = var_description(
true, is_complex(),
true, niter,
857 VDESCRFILTER_NO, &mf);
858 variables[name].set_size();
860 act_size_to_be_done =
true;
861 leading_dim = std::max(leading_dim, mf.
linked_mesh().dim());
867 check_name_validity(name);
868 variables[name] = var_description(
true, is_complex(),
true, niter,
869 VDESCRFILTER_REGION, &mf, region);
870 variables[name].set_size();
871 act_size_to_be_done =
true;
876 const std::string &org_name,
878 check_name_validity(name);
879 VAR_SET::const_iterator it = find_variable(org_name);
880 GMM_ASSERT1(it->second.is_variable && !(it->second.is_affine_dependent),
881 "The original variable should be a variable");
882 variables[name] = variables[org_name];
883 variables[name].is_affine_dependent =
true;
884 variables[name].org_name = org_name;
885 variables[name].alpha = alpha;
886 variables[name].set_size();
891 check_name_validity(name);
892 variables[name] = var_description(
false, is_complex(),
true, niter,
893 VDESCRFILTER_NO, &mf);
894 variables[name].qdims[0] = qdim;
895 GMM_ASSERT1(qdim,
"Data of null size are not allowed");
896 variables[name].set_size();
901 const bgeot::multi_index &sizes,
size_type niter) {
902 check_name_validity(name);
903 variables[name] = var_description(
false, is_complex(),
true, niter,
904 VDESCRFILTER_NO, &mf);
905 variables[name].qdims = sizes;
906 GMM_ASSERT1(variables[name].qdim(),
"Data of null size are not allowed");
907 variables[name].set_size();
912 const std::string &primal_name,
914 check_name_validity(name);
915 variables[name] = var_description(
true, is_complex(),
true, niter,
916 VDESCRFILTER_CTERM, &mf, 0,
917 bgeot::multi_index(), primal_name);
918 variables[name].set_size();
919 act_size_to_be_done =
true;
924 size_type region,
const std::string &primal_name,
926 check_name_validity(name);
927 variables[name] = var_description(
true, is_complex(),
true, niter,
928 VDESCRFILTER_REGION_CTERM, &mf, region,
929 bgeot::multi_index(), primal_name);
930 variables[name].set_size();
931 act_size_to_be_done =
true;
936 const std::string &primal_name,
const mesh_im &mim,
938 check_name_validity(name);
939 variables[name] = var_description(
true, is_complex(),
true, niter,
940 VDESCRFILTER_INFSUP, &mf, region,
941 bgeot::multi_index(), primal_name, &mim);
942 variables[name].set_size();
943 act_size_to_be_done =
true;
948 VAR_SET::iterator it = variables.find(name);
949 GMM_ASSERT1(it != variables.end(),
"Undefined variable " << name);
950 it->second.is_disabled =
true;
951 for (VAR_SET::iterator itv = variables.begin();
952 itv != variables.end(); ++itv) {
953 if (((itv->second.filter & VDESCRFILTER_INFSUP) ||
954 (itv->second.filter & VDESCRFILTER_CTERM))
955 && (name.compare(itv->second.filter_var) == 0)) {
956 itv->second.is_disabled =
true;
958 if (itv->second.is_variable && itv->second.is_affine_dependent
959 && name.compare(itv->second.org_name) == 0)
960 itv->second.is_disabled =
true;
962 if (!act_size_to_be_done) resize_global_system();
966 VAR_SET::iterator it = variables.find(name);
967 GMM_ASSERT1(it != variables.end(),
"Undefined variable " << name);
968 it->second.is_disabled =
false;
969 for (VAR_SET::iterator itv = variables.begin();
970 itv != variables.end(); ++itv) {
971 if (((itv->second.filter & VDESCRFILTER_INFSUP) ||
972 (itv->second.filter & VDESCRFILTER_CTERM))
973 && (name.compare(itv->second.filter_var) == 0)) {
974 itv->second.is_disabled =
false;
976 if (itv->second.is_variable && itv->second.is_affine_dependent
977 && name.compare(itv->second.org_name) == 0)
978 itv->second.is_disabled =
false;
980 if (!act_size_to_be_done) resize_global_system();
988 check_name_validity(name.substr(0, name.find(
"(")));
989 macro_dict.add_macro(name, expr);
993 { macro_dict.del_macro(name); }
996 GMM_ASSERT1(valid_bricks[ib],
"Inexistent brick");
997 valid_bricks.del(ib);
998 active_bricks.del(ib);
1000 for (
size_type i = 0; i < bricks[ib].mims.size(); ++i) {
1001 const mesh_im *mim = bricks[ib].mims[i];
1003 for (dal::bv_visitor ibb(valid_bricks); !ibb.finished(); ++ibb) {
1004 for (
size_type j = 0; j < bricks[ibb].mims.size(); ++j)
1005 if (bricks[ibb].mims[j] == mim) found =
true;
1007 for(VAR_SET::iterator it2 = variables.begin();
1008 it2 != variables.end(); ++it2) {
1009 if (it2->second.is_fem_dofs &&
1010 (it2->second.filter & VDESCRFILTER_INFSUP) &&
1011 mim == it2->second.mim) found =
true;
1013 if (!found) sup_dependency(*mim);
1016 is_linear_ = is_symmetric_ = is_coercive_ =
true;
1017 for (dal::bv_visitor ibb(valid_bricks); !ibb.finished(); ++ibb) {
1018 is_linear_ = is_linear_ && bricks[ibb].pbr->is_linear();
1019 is_symmetric_ = is_symmetric_ && bricks[ibb].pbr->is_symmetric();
1020 is_coercive_ = is_coercive_ && bricks[ibb].pbr->is_coercive();
1023 bricks[ib] = brick_description();
1027 for (dal::bv_visitor ibb(valid_bricks); !ibb.finished(); ++ibb) {
1028 for (
size_type i = 0; i < bricks[ibb].vlist.size(); ++i)
1029 GMM_ASSERT1(varname.compare(bricks[ibb].vlist[i]),
1030 "Cannot delete a variable which is still use by a brick");
1031 for (
size_type i = 0; i < bricks[ibb].dlist.size(); ++i)
1032 GMM_ASSERT1(varname.compare(bricks[ibb].dlist[i]),
1033 "Cannot delete a data which is still use by a brick");
1036 VAR_SET::const_iterator it = find_variable(varname);
1038 if (it->second.is_fem_dofs) {
1039 const mesh_fem *mf = it->second.mf;
1041 for(VAR_SET::iterator it2 = variables.begin();
1042 it2 != variables.end(); ++it2) {
1043 if (it != it2 && it2->second.is_fem_dofs && mf == it2->second.mf)
1046 if (!found) sup_dependency(*mf);
1048 if (it->second.filter & VDESCRFILTER_INFSUP) {
1049 const mesh_im *mim = it->second.mim;
1051 for (dal::bv_visitor ibb(valid_bricks); !ibb.finished(); ++ibb) {
1052 for (
size_type j = 0; j < bricks[ibb].mims.size(); ++j)
1053 if (bricks[ibb].mims[j] == mim) found =
true;
1055 for(VAR_SET::iterator it2 = variables.begin();
1056 it2 != variables.end(); ++it2) {
1057 if (it != it2 && it2->second.is_fem_dofs &&
1058 (it2->second.filter & VDESCRFILTER_INFSUP) &&
1059 mim == it2->second.mim) found =
true;
1061 if (!found) sup_dependency(*mim);
1065 if (it->second.pim_data != 0) sup_dependency(*(it->second.pim_data));
1067 variables.erase(varname);
1068 act_size_to_be_done =
true;
1072 const varnamelist &datanames,
1073 const termlist &terms,
1074 const mimlist &mims,
size_type region) {
1075 size_type ib = valid_bricks.first_false();
1077 for (
size_type i = 0; i < terms.size(); ++i)
1078 if (terms[i].is_global && terms[i].is_matrix_term && pbr->is_linear())
1079 GMM_ASSERT1(
false,
"Global linear matrix terms are not allowed");
1081 if (ib == bricks.size())
1082 bricks.push_back(brick_description(pbr, varnames, datanames, terms,
1085 bricks[ib] = brick_description(pbr, varnames, datanames, terms,
1087 active_bricks.add(ib);
1088 valid_bricks.add(ib);
1091 for (
size_type i = 0; i < bricks[ib].mims.size(); ++i)
1092 add_dependency(*(bricks[ib].mims[i]));
1094 GMM_ASSERT1(pbr->is_real() || is_complex(),
1095 "Impossible to add a complex brick to a real model");
1096 if (is_complex() && pbr->is_complex()) {
1097 bricks[ib].cmatlist.resize(terms.size());
1098 bricks[ib].cveclist[0].resize(terms.size());
1099 bricks[ib].cveclist_sym[0].resize(terms.size());
1101 bricks[ib].rmatlist.resize(terms.size());
1102 bricks[ib].rveclist[0].resize(terms.size());
1103 bricks[ib].rveclist_sym[0].resize(terms.size());
1105 is_linear_ = is_linear_ && pbr->is_linear();
1106 is_symmetric_ = is_symmetric_ && pbr->is_symmetric();
1107 is_coercive_ = is_coercive_ && pbr->is_coercive();
1109 for (
size_type i=0; i < varnames.size(); ++i)
1110 GMM_ASSERT1(variables.find(varnames[i]) != variables.end(),
1111 "Undefined model variable " << varnames[i]);
1113 for (
size_type i=0; i < datanames.size(); ++i)
1114 GMM_ASSERT1(variables.find(datanames[i]) != variables.end(),
1115 "Undefined model data or variable " << datanames[i]);
1121 GMM_ASSERT1(valid_bricks[ib],
"Inexistent brick");
1123 bricks[ib].mims.push_back(&mim);
1124 add_dependency(mim);
1128 GMM_ASSERT1(valid_bricks[ib],
"Inexistent brick");
1130 bricks[ib].tlist = terms;
1131 if (is_complex() && bricks[ib].pbr->is_complex()) {
1132 bricks.back().cmatlist.resize(terms.size());
1133 bricks.back().cveclist[0].resize(terms.size());
1134 bricks.back().cveclist_sym[0].resize(terms.size());
1136 bricks.back().rmatlist.resize(terms.size());
1137 bricks.back().rveclist[0].resize(terms.size());
1138 bricks.back().rveclist_sym[0].resize(terms.size());
1143 GMM_ASSERT1(valid_bricks[ib],
"Inexistent brick");
1145 bricks[ib].vlist = vl;
1147 GMM_ASSERT1(variables.find(vl[i]) != variables.end(),
1148 "Undefined model variable " << vl[i]);
1152 GMM_ASSERT1(valid_bricks[ib],
"Inexistent brick");
1154 bricks[ib].dlist = dl;
1156 GMM_ASSERT1(variables.find(dl[i]) != variables.end(),
1157 "Undefined model variable " << dl[i]);
1161 GMM_ASSERT1(valid_bricks[ib],
"Inexistent brick");
1163 bricks[ib].mims = ml;
1164 for (
size_type i = 0; i < ml.size(); ++i) add_dependency(*(ml[i]));
1168 GMM_ASSERT1(valid_bricks[ib],
"Inexistent brick");
1170 bricks[ib].is_update_brick = flag;
1173 void model::set_time(scalar_type t,
bool to_init) {
1174 static const std::string varname(
"t");
1175 VAR_SET::iterator it = variables.find(varname);
1176 if (it == variables.end()) {
1177 add_fixed_size_data(varname, 1);
1179 GMM_ASSERT1(it->second.size() == 1,
"Time data should be of size 1");
1181 if (it == variables.end() || to_init) {
1183 set_complex_variable(varname)[0] = complex_type(t);
1185 set_real_variable(varname)[0] = t;
1189 scalar_type model::get_time() {
1190 static const std::string varname(
"t");
1191 set_time(scalar_type(0),
false);
1193 return gmm::real(complex_variable(varname)[0]);
1195 return real_variable(varname)[0];
1198 void model::call_init_affine_dependent_variables(
int version) {
1199 for (VAR_SET::iterator it = variables.begin();
1200 it != variables.end(); ++it)
1201 if (it->second.is_variable && it->second.ptsc) {
1203 it->second.ptsc->init_affine_dependent_variables_precomputation(*
this);
1205 it->second.ptsc->init_affine_dependent_variables(*
this);
1209 void model::shift_variables_for_time_integration() {
1210 for (VAR_SET::iterator it = variables.begin();
1211 it != variables.end(); ++it)
1212 if (it->second.is_variable && it->second.ptsc)
1213 it->second.ptsc->shift_variables(*
this);
1216 void model::add_time_integration_scheme(
const std::string &varname,
1217 ptime_scheme ptsc) {
1218 VAR_SET::iterator it = variables.find(varname);
1219 GMM_ASSERT1(it != variables.end(),
"Undefined variable " << varname);
1220 GMM_ASSERT1(it->second.is_variable && !(it->second.is_affine_dependent),
1221 "Cannot apply an integration scheme to " << varname);
1222 it->second.ptsc = ptsc;
1229 time_integration = 1;
1232 void model::copy_init_time_derivative() {
1234 for (VAR_SET::iterator it = variables.begin();
1235 it != variables.end(); ++it)
1236 if (it->second.is_variable && it->second.ptsc) {
1238 std::string name_v, name_previous_v;
1239 it->second.ptsc->time_derivative_to_be_intialized(name_v,
1242 if (name_v.size()) {
1244 model_complex_plain_vector v0 = this->complex_variable(name_v);
1245 gmm::copy(v0, this->set_complex_variable(name_previous_v));
1247 const model_real_plain_vector &v0 = this->real_variable(name_v);
1248 gmm::copy(v0, this->set_real_variable(name_previous_v));
1260 class APIDECL first_order_theta_method_scheme
1263 std::string U, U0, V, V0;
1268 virtual void init_affine_dependent_variables(
model &md)
const {
1269 scalar_type dt = md.get_time_step();
1270 scalar_type a = scalar_type(1)/(theta*dt);
1271 scalar_type b = (scalar_type(1)-theta)/theta;
1272 md.set_factor_of_variable(V, a);
1276 md.set_complex_constant_part(V));
1281 md.set_real_constant_part(V));
1286 virtual void init_affine_dependent_variables_precomputation(
model &md)
1288 scalar_type dt = md.get_time_step();
1289 md.set_factor_of_variable(V, scalar_type(1)/dt);
1292 md.set_complex_constant_part(V));
1295 gmm::copy(gmm::scaled(md.
real_variable(U0), -scalar_type(1)/dt),
1296 md.set_real_constant_part(V));
1300 virtual void time_derivative_to_be_intialized
1301 (std::string &name_v, std::string &name_previous_v)
const 1302 {
if (theta != scalar_type(1)) { name_v = V; name_previous_v = V0; } }
1304 virtual void shift_variables(
model &md)
const {
1315 first_order_theta_method_scheme(
model &md, std::string varname,
1318 U0 =
"Previous_" + U;
1320 V0 =
"Previous_Dot_" + U;
1322 GMM_ASSERT1(theta > scalar_type(0) && theta <= scalar_type(1),
1323 "Invalid value of theta parameter for the theta-method");
1343 void add_theta_method_for_first_order(
model &md,
const std::string &varname,
1344 scalar_type theta) {
1346 = std::make_shared<first_order_theta_method_scheme>(md, varname,theta);
1347 md.add_time_integration_scheme(varname, ptsc);
1356 class APIDECL second_order_theta_method_scheme
1359 std::string U, U0, V, V0, A, A0;
1365 virtual void init_affine_dependent_variables(
model &md)
const {
1366 scalar_type dt = md.get_time_step();
1367 md.set_factor_of_variable(V, scalar_type(1)/(theta*dt));
1368 md.set_factor_of_variable(A, scalar_type(1)/(theta*theta*dt*dt));
1371 -complex_type(1)/(theta*dt)),
1373 -(complex_type(1)-complex_type(theta))/theta),
1374 md.set_complex_constant_part(V));
1376 -complex_type(1)/(theta*theta*dt*dt)),
1378 -(complex_type(1)-complex_type(theta))/theta),
1379 md.set_complex_constant_part(A));
1381 -complex_type(1)/(theta*theta*dt)),
1382 md.set_complex_constant_part(A));
1387 -scalar_type(1)/(theta*dt)),
1389 -(scalar_type(1)-theta)/theta),
1390 md.set_real_constant_part(V));
1392 -scalar_type(1)/(theta*theta*dt*dt)),
1394 -(scalar_type(1)-theta)/theta),
1395 md.set_real_constant_part(A));
1397 -scalar_type(1)/(theta*theta*dt)),
1398 md.set_real_constant_part(A));
1405 virtual void init_affine_dependent_variables_precomputation(
model &md)
1407 scalar_type dt = md.get_time_step();
1408 md.set_factor_of_variable(V, scalar_type(1)/dt);
1409 md.set_factor_of_variable(A, scalar_type(1)/(dt*dt));
1412 -complex_type(1)/dt),
1413 md.set_complex_constant_part(V));
1415 -complex_type(1)/(dt*dt)),
1417 -complex_type(1)/dt),
1418 md.set_complex_constant_part(A));
1421 -scalar_type(1)/dt),
1422 md.set_real_constant_part(V));
1424 -scalar_type(1)/(dt*dt)),
1426 -scalar_type(1)/dt),
1427 md.set_real_constant_part(A));
1431 virtual void time_derivative_to_be_intialized
1432 (std::string &name_v, std::string &name_previous_v)
const 1433 {
if (theta != scalar_type(1)) { name_v = A; name_previous_v = A0; } }
1435 virtual void shift_variables(
model &md)
const {
1448 second_order_theta_method_scheme(
model &md, std::string varname,
1451 U0 =
"Previous_" + U;
1453 V0 =
"Previous_Dot_" + U;
1455 A0 =
"Previous_Dot2_" + U;
1457 GMM_ASSERT1(theta > scalar_type(0) && theta <= scalar_type(1),
1458 "Invalid value of theta parameter for the theta-method");
1483 void add_theta_method_for_second_order(
model &md,
const std::string &varname,
1484 scalar_type theta) {
1485 ptime_scheme ptsc = std::make_shared<second_order_theta_method_scheme>
1487 md.add_time_integration_scheme(varname, ptsc);
1497 class APIDECL Newmark_scheme
1500 std::string U, U0, V, V0, A, A0;
1501 scalar_type beta, gamma;
1506 virtual void init_affine_dependent_variables(
model &md)
const {
1507 scalar_type dt = md.get_time_step();
1508 scalar_type a0 = scalar_type(1)/(beta*dt*dt), a1 = dt*a0;
1509 scalar_type a2 = (scalar_type(1) - scalar_type(2)*beta)
1510 / (scalar_type(2)*beta);
1511 scalar_type b0 = gamma/(beta*dt), b1 = (beta-gamma)/beta;
1512 scalar_type b2 = dt*(1-gamma/(scalar_type(2)*beta));
1514 md.set_factor_of_variable(V, b0);
1515 md.set_factor_of_variable(A, a0);
1519 md.set_complex_constant_part(V));
1521 md.set_complex_constant_part(V));
1524 md.set_complex_constant_part(A));
1526 md.set_complex_constant_part(A));
1530 md.set_real_constant_part(V));
1532 md.set_real_constant_part(V));
1535 md.set_real_constant_part(A));
1537 md.set_real_constant_part(A));
1544 virtual void init_affine_dependent_variables_precomputation(
model &md)
1546 scalar_type dt = md.get_time_step();
1547 md.set_factor_of_variable(V, scalar_type(1)/dt);
1548 md.set_factor_of_variable(A, scalar_type(1)/(dt*dt));
1551 -complex_type(1)/dt),
1552 md.set_complex_constant_part(V));
1554 -complex_type(1)/(dt*dt)),
1556 -complex_type(1)/dt),
1557 md.set_complex_constant_part(A));
1560 -scalar_type(1)/dt),
1561 md.set_real_constant_part(V));
1563 -scalar_type(1)/(dt*dt)),
1565 -scalar_type(1)/dt),
1566 md.set_real_constant_part(A));
1570 virtual void time_derivative_to_be_intialized
1571 (std::string &name_v, std::string &name_previous_v)
const {
1572 if (beta != scalar_type(0.5) || gamma != scalar_type(1))
1573 { name_v = A; name_previous_v = A0; }
1576 virtual void shift_variables(
model &md)
const {
1589 Newmark_scheme(
model &md, std::string varname,
1590 scalar_type be, scalar_type ga) {
1592 U0 =
"Previous_" + U;
1594 V0 =
"Previous_Dot_" + U;
1596 A0 =
"Previous_Dot2_" + U;
1597 beta = be; gamma = ga;
1598 GMM_ASSERT1(beta > scalar_type(0) && beta <= scalar_type(1)
1599 && gamma >= scalar_type(0.5) && gamma <= scalar_type(1),
1600 "Invalid parameter values for the Newmark scheme");
1625 void add_Newmark_scheme(
model &md,
const std::string &varname,
1626 scalar_type beta, scalar_type gamma) {
1627 ptime_scheme ptsc = std::make_shared<Newmark_scheme>
1628 (md, varname, beta, gamma);
1629 md.add_time_integration_scheme(varname, ptsc);
1642 GMM_ASSERT1(valid_bricks[ibrick],
"Inexistent brick");
1643 pbrick pbr = bricks[ibrick].pbr;
1645 bricks[ibrick].pdispatch = pdispatch;
1648 = std::max(
size_type(1), pdispatch->nbrhs());
1650 gmm::resize(bricks[ibrick].coeffs, nbrhs);
1652 if (is_complex() && pbr->is_complex()) {
1653 bricks[ibrick].cveclist.resize(nbrhs);
1654 bricks[ibrick].cveclist_sym.resize(nbrhs);
1656 bricks[ibrick].cveclist[k] = bricks[ibrick].cveclist[0];
1657 bricks[ibrick].cveclist_sym[k] = bricks[ibrick].cveclist_sym[0];
1660 bricks[ibrick].rveclist.resize(nbrhs);
1661 bricks[ibrick].rveclist_sym.resize(nbrhs);
1663 bricks[ibrick].rveclist[k] = bricks[ibrick].rveclist[0];
1664 bricks[ibrick].rveclist_sym[k] = bricks[ibrick].rveclist_sym[0];
1671 GMM_ASSERT1(valid_bricks[ind_brick],
"Inexistent brick");
1672 GMM_ASSERT1(ind_var < bricks[ind_brick].vlist.size(),
1673 "Inexistent brick variable");
1674 return bricks[ind_brick].vlist[ind_var];
1679 GMM_ASSERT1(valid_bricks[ind_brick],
"Inexistent brick");
1680 GMM_ASSERT1(ind_data < bricks[ind_brick].dlist.size(),
1681 "Inexistent brick data");
1682 return bricks[ind_brick].dlist[ind_data];
1686 if (valid_bricks.card() == 0)
1687 ost <<
"Model with no bricks" << endl;
1689 ost <<
"List of model bricks:" << endl;
1690 for (dal::bv_visitor i(valid_bricks); !i.finished(); ++i) {
1691 ost <<
"Brick " << std::setw(3) << std::right << i + base_id
1692 <<
" " << std::setw(20) << std::right
1693 << bricks[i].pbr->brick_name();
1694 if (!(active_bricks[i])) ost <<
" (desactivated)";
1695 if (bricks[i].pdispatch) ost <<
" (dispatched)";
1696 ost << endl <<
" concerned variables: " << bricks[i].vlist[0];
1697 for (
size_type j = 1; j < bricks[i].vlist.size(); ++j)
1698 ost <<
", " << bricks[i].vlist[j];
1700 ost <<
" brick with " << bricks[i].tlist.size() <<
" term";
1701 if (bricks[i].tlist.size() > 1) ost <<
"s";
1710 void model::brick_init(
size_type ib, build_version version,
1712 const brick_description &brick = bricks[ib];
1713 bool cplx = is_complex() && brick.pbr->is_complex();
1716 for (
size_type j = 0; j < brick.tlist.size(); ++j) {
1717 const term_description &term = brick.tlist[j];
1718 bool isg = term.is_global;
1720 gmm::vect_size(crhs) : gmm::vect_size(rrhs);
1721 size_type nbd1 = isg ? nbgdof : variables[term.var1].size();
1722 size_type nbd2 = isg ? nbgdof : (term.is_matrix_term ?
1723 variables[term.var2].size() : 0);
1724 if (term.is_matrix_term &&
1725 (brick.pbr->is_linear() || (version | BUILD_MATRIX))) {
1726 if (version | BUILD_ON_DATA_CHANGE) {
1728 gmm::resize(brick.cmatlist[j], nbd1, nbd2);
1730 gmm::resize(brick.rmatlist[j], nbd1, nbd2);
1733 brick.cmatlist[j] = model_complex_sparse_matrix(nbd1, nbd2);
1735 brick.rmatlist[j] = model_real_sparse_matrix(nbd1, nbd2);
1738 if (brick.pbr->is_linear() || (version | BUILD_RHS)) {
1739 for (
size_type k = 0; k < brick.nbrhs; ++k) {
1741 if (k == rhs_ind) gmm::clear(brick.cveclist[k][j]);
1742 gmm::resize(brick.cveclist[k][j], nbd1);
1743 if (term.is_symmetric && term.var1.compare(term.var2)) {
1744 if (k == rhs_ind) gmm::clear(brick.cveclist_sym[k][j]);
1745 gmm::resize(brick.cveclist_sym[k][j], nbd2);
1748 if (k == rhs_ind) gmm::clear(brick.rveclist[k][j]);
1749 gmm::resize(brick.rveclist[k][j], nbd1);
1750 if (term.is_symmetric && term.var1.compare(term.var2)) {
1751 if (k == rhs_ind) gmm::clear(brick.rveclist_sym[k][j]);
1752 gmm::resize(brick.rveclist_sym[k][j], nbd2);
1760 void model::post_to_variables_step(){}
1770 CONTAINER_LIST& original_list;
1772 typedef typename CONTAINER_LIST::value_type value_type;
1774 void build_distro(gmm::abstract_matrix)
1778 for(
size_type thread = 1; thread < num_threads(); thread++)
1780 auto it_original = original_list.begin();
1781 auto it_distributed = distributed_list(thread).begin();
1782 for(;it_original != original_list.end(); ++it_original, ++it_distributed)
1784 gmm::resize(*it_distributed, gmm::mat_nrows(*it_original),gmm::mat_ncols(*it_original));
1789 void build_distro(gmm::abstract_vector)
1792 for(
size_type thread = 1; thread < num_threads(); thread++)
1794 auto it_original = original_list.begin();
1795 auto it_distributed = distributed_list(thread).begin();
1796 for(;it_original != original_list.end(); ++it_original, ++it_distributed)
1798 gmm::resize(*it_distributed, gmm::vect_size(*it_original));
1803 bool not_multithreaded()
const {
return num_threads() == 1; }
1809 if (not_multithreaded())
return;
1811 for(
size_type thread=1; thread<num_threads(); thread++)
1812 distributed_list(thread).resize(original_list.size());
1814 build_distro(
typename gmm::linalg_traits<value_type>::linalg_type());
1817 operator CONTAINER_LIST&()
1819 if (not_multithreaded() || this_thread() == 0)
return original_list;
1820 else return distributed_list(this_thread());
1825 if (not_multithreaded())
return;
1827 GMM_ASSERT1(!me_is_multithreaded_now(),
1828 "List accumulation should not run in parallel");
1830 using namespace std;
1831 auto to_add = vector<CONTAINER_LIST*>{};
1832 to_add.push_back(&original_list);
1833 for (
size_type thread = 1; thread < num_threads(); ++thread)
1834 to_add.push_back(&distributed_list(thread));
1840 while (to_add.size() > 1)
1842 #pragma omp parallel default(shared) 1844 auto i = this_thread() * 2;
1845 if (i + 1 < to_add.size()){
1846 auto &target = *to_add[i];
1847 auto &source = *to_add[i + 1];
1848 for (
size_type j = 0; j < source.size(); ++j) gmm::add(source[j], target[j]);
1852 for (
auto it = begin(to_add); it < end(to_add);){
1853 if (next(it) < end(to_add)) it = to_add.erase(next(it));
1859 void model::brick_call(
size_type ib, build_version version,
1862 const brick_description &brick = bricks[ib];
1863 bool cplx = is_complex() && brick.pbr->is_complex();
1865 brick_init(ib, version, rhs_ind);
1869 brick.pbr->complex_pre_assembly_in_serial(*
this, ib, brick.vlist,
1870 brick.dlist, brick.mims,
1872 brick.cveclist[rhs_ind],
1873 brick.cveclist_sym[rhs_ind],
1874 brick.region, version);
1885 open_mp_is_running_properly check;
1887 #pragma omp parallel default(shared) 1891 brick.pbr->asm_complex_tangent_terms(*
this, ib, brick.vlist,
1892 brick.dlist, brick.mims,
1896 brick.region, version);
1899 exception.rethrow();
1901 brick.pbr->complex_post_assembly_in_serial(*
this, ib, brick.vlist,
1902 brick.dlist, brick.mims,
1904 brick.cveclist[rhs_ind],
1905 brick.cveclist_sym[rhs_ind],
1906 brick.region, version);
1908 if (brick.is_update_brick)
1910 for (
size_type i = 0; i < brick.cmatlist.size(); ++i)
1912 gmm::clear(brick.cmatlist[i]);
1915 for (
size_type i = 0; i < brick.cveclist.size(); ++i)
1916 for (
size_type j = 0; j < brick.cveclist[i].size(); ++j)
1918 gmm::clear(brick.cveclist[i][j]);
1921 for (
size_type i = 0; i < brick.cveclist_sym.size(); ++i)
1922 for (
size_type j = 0; j < brick.cveclist_sym[i].size(); ++j)
1924 gmm::clear(brick.cveclist_sym[i][j]);
1930 brick.pbr->real_pre_assembly_in_serial(*
this, ib, brick.vlist,
1931 brick.dlist, brick.mims,
1933 brick.rveclist[rhs_ind],
1934 brick.rveclist_sym[rhs_ind],
1935 brick.region, version);
1944 open_mp_is_running_properly check;
1946 #pragma omp parallel default(shared) 1950 brick.pbr->asm_real_tangent_terms(*
this, ib, brick.vlist,
1951 brick.dlist, brick.mims,
1959 exception.rethrow();
1961 brick.pbr->real_post_assembly_in_serial(*
this, ib, brick.vlist,
1962 brick.dlist, brick.mims,
1964 brick.rveclist[rhs_ind],
1965 brick.rveclist_sym[rhs_ind],
1966 brick.region, version);
1968 if (brick.is_update_brick)
1970 for (
size_type i = 0; i < brick.rmatlist.size(); ++i)
1972 gmm::clear(brick.rmatlist[i]);
1975 for (
size_type i = 0; i < brick.rveclist.size(); ++i)
1976 for (
size_type j = 0; j < brick.rveclist[i].size(); ++j)
1978 gmm::clear(brick.rveclist[i][j]);
1981 for (
size_type i = 0; i < brick.rveclist_sym.size(); ++i)
1982 for (
size_type j = 0; j < brick.rveclist_sym[i].size(); ++j)
1984 gmm::clear(brick.rveclist_sym[i][j]);
1991 void model::set_dispatch_coeff() {
1992 for (dal::bv_visitor ib(active_bricks); !ib.finished(); ++ib) {
1993 brick_description &brick = bricks[ib];
1994 if (brick.pdispatch)
1995 brick.pdispatch->set_dispatch_coeff(*
this, ib);
2001 context_check();
if (act_size_to_be_done) actualize_sizes();
2002 for (VAR_SET::iterator it = variables.begin(); it != variables.end(); ++it)
2003 it->second.clear_temporaries();
2005 set_dispatch_coeff();
2007 for (dal::bv_visitor ib(active_bricks); !ib.finished(); ++ib) {
2008 brick_description &brick = bricks[ib];
2009 bool cplx = is_complex() && brick.pbr->is_complex();
2010 if (brick.pdispatch) {
2012 brick.pdispatch->next_complex_iter(*
this, ib, brick.vlist,
2014 brick.cmatlist, brick.cveclist,
2015 brick.cveclist_sym,
true);
2017 brick.pdispatch->next_real_iter(*
this, ib, brick.vlist, brick.dlist,
2018 brick.rmatlist, brick.rveclist,
2019 brick.rveclist_sym,
true);
2025 context_check();
if (act_size_to_be_done) actualize_sizes();
2026 set_dispatch_coeff();
2028 for (dal::bv_visitor ib(active_bricks); !ib.finished(); ++ib) {
2029 brick_description &brick = bricks[ib];
2030 bool cplx = is_complex() && brick.pbr->is_complex();
2031 if (brick.pdispatch) {
2033 brick.pdispatch->next_complex_iter(*
this, ib, brick.vlist,
2035 brick.cmatlist, brick.cveclist,
2036 brick.cveclist_sym,
false);
2038 brick.pdispatch->next_real_iter(*
this, ib, brick.vlist, brick.dlist,
2039 brick.rmatlist, brick.rveclist,
2040 brick.rveclist_sym,
false);
2044 for (VAR_SET::iterator it = variables.begin(); it != variables.end();
2046 for (
size_type i = 1; i < it->second.n_iter; ++i) {
2048 gmm::copy(it->second.complex_value[i-1],
2049 it->second.complex_value[i]);
2051 gmm::copy(it->second.real_value[i-1],
2052 it->second.real_value[i]);
2053 it->second.v_num_data[i] = act_counter();
2058 bool model::is_var_newer_than_brick(
const std::string &varname,
2060 const brick_description &brick = bricks[ib];
2061 var_description &vd = variables[varname];
2062 if (niter ==
size_type(-1)) niter = vd.default_iter;
2063 return (vd.v_num > brick.v_num || vd.v_num_data[niter] > brick.v_num);
2066 bool model::is_var_mf_newer_than_brick(
const std::string &varname,
2068 const brick_description &brick = bricks[ib];
2069 var_description &vd = variables[varname];
2070 return (vd.v_num > brick.v_num);
2073 bool model::is_mim_newer_than_brick(
const mesh_im &im,
2075 const brick_description &brick = bricks[ib];
2076 return (im.version_number() > brick.v_num);
2079 void model::define_variable_group(
const std::string &group_name,
2080 const std::vector<std::string> &nl) {
2081 GMM_ASSERT1(!(variable_exists(group_name)),
"The name of a group of " 2082 "variables cannot be the same as a variable name");
2084 std::set<const mesh *> ms;
2085 bool is_data_ =
false;
2086 for (
size_type i = 0; i < nl.size(); ++i) {
2088 is_data_ = is_true_data(nl[i]);
2090 GMM_ASSERT1(is_data_ == is_true_data(nl[i]),
2091 "It is not possible to mix variables and data in a group");
2093 GMM_ASSERT1(variable_exists(nl[i]),
2094 "All variables in a group have to exist in the model");
2095 const mesh_fem *mf = pmesh_fem_of_variable(nl[i]);
2096 GMM_ASSERT1(mf,
"Variables in a group should be fem variables");
2097 GMM_ASSERT1(ms.find(&(mf->
linked_mesh())) == ms.end(),
2098 "Two variables in a group cannot share the same mesh");
2101 variable_groups[group_name] = nl;
2104 void model::add_assembly_assignments(
const std::string &varname,
2107 GMM_ASSERT1(order < 3 || order ==
size_type(-1),
"Bad order value");
2108 const im_data *imd = pim_data_of_variable(varname);
2109 GMM_ASSERT1(imd != 0,
"Only applicable to im_data");
2110 assignement_desc as;
2111 as.varname = varname; as.expr = expr; as.region = rg; as.order = order;
2113 assignments.push_back(as);
2116 void model::add_temporaries(
const varnamelist &vl,
2117 gmm::uint64_type id_num)
const {
2118 for (
size_type i = 0; i < vl.size(); ++i) {
2119 var_description &vd = variables[vl[i]];
2120 if (vd.n_iter > 1) {
2121 vd.add_temporary(id_num);
2126 bool model::temporary_uptodate(
const std::string &varname,
2127 gmm::uint64_type id_num,
2129 var_description &vd = variables[varname];
2131 for (; ind < vd.n_iter + vd.n_temp_iter ; ++ind) {
2132 if (vd.v_num_var_iter[ind] == id_num)
break;
2134 if (ind < vd.n_iter + vd.n_temp_iter) {
2135 if (vd.v_num_iter[ind] <= vd.v_num_data[vd.default_iter]) {
2136 vd.v_num_iter[ind] = act_counter();
2145 void model::set_default_iter_of_variable(
const std::string &varname,
2148 var_description &vd = variables[varname];
2149 GMM_ASSERT1(ind < vd.n_iter + vd.n_temp_iter,
2150 "Inexistent iteration " << ind);
2151 vd.default_iter = ind;
2155 void model::reset_default_iter_of_variables(
const varnamelist &vl)
const {
2156 for (
size_type i = 0; i < vl.size(); ++i)
2157 variables[vl[i]].default_iter = 0;
2160 const model_real_sparse_matrix &
2162 GMM_ASSERT1(bricks[ib].tlist[iterm].is_matrix_term,
2163 "Not a matrix term !");
2164 GMM_ASSERT1(bricks[ib].pbr->is_linear(),
"Nonlinear term !");
2165 return bricks[ib].rmatlist[iterm];
2168 const model_complex_sparse_matrix &
2170 GMM_ASSERT1(bricks[ib].tlist[iterm].is_matrix_term,
2171 "Not a matrix term !");
2172 GMM_ASSERT1(bricks[ib].pbr->is_linear(),
"Nonlinear term !");
2173 return bricks[ib].cmatlist[iterm];
2177 void model::update_brick(
size_type ib, build_version version)
const {
2178 const brick_description &brick = bricks[ib];
2179 bool cplx = is_complex() && brick.pbr->is_complex();
2180 bool tobecomputed = brick.terms_to_be_computed
2181 || brick.pbr->is_to_be_computed_each_time()
2182 || !(brick.pbr->is_linear());
2185 if (!tobecomputed ) {
2186 for (
size_type i = 0; i < brick.vlist.size() && !tobecomputed; ++i) {
2187 var_description &vd = variables[brick.vlist[i]];
2188 if (vd.v_num > brick.v_num) tobecomputed =
true;
2193 for (
size_type i = 0; i < brick.dlist.size() && !tobecomputed; ++i) {
2194 var_description &vd = variables[brick.dlist[i]];
2195 if (vd.v_num > brick.v_num || vd.v_num_data[vd.default_iter] > brick.v_num) {
2196 tobecomputed =
true;
2197 version = build_version(version | BUILD_ON_DATA_CHANGE);
2202 brick.external_load = scalar_type(0);
2204 if (!(brick.pdispatch))
2205 { brick_call(ib, version, 0); }
2208 brick.pdispatch->asm_complex_tangent_terms
2209 (*
this, ib, brick.cmatlist, brick.cveclist, brick.cveclist_sym,
2212 brick.pdispatch->asm_real_tangent_terms
2213 (*
this, ib, brick.rmatlist, brick.rveclist, brick.rveclist_sym,
2216 brick.v_num = act_counter();
2219 if (brick.pbr->is_linear()) brick.terms_to_be_computed =
false;
2226 const brick_description &brick = bricks[ib];
2227 if (brick.pbr->is_linear()) {
2229 bool cplx = is_complex() && brick.pbr->is_complex();
2231 for (
size_type j = 0; j < brick.tlist.size(); ++j) {
2232 const term_description &term = brick.tlist[j];
2233 bool isg = term.is_global;
2236 size_type n_iter_1 = n_iter, n_iter_2 = n_iter;
2238 n_iter_1 = variables[term.var1].default_iter;
2239 if (term.is_matrix_term)
2240 n_iter_2 = variables[term.var2].default_iter;
2245 if (term.is_matrix_term) {
2248 model_complex_plain_vector V(nbgdof);
2249 for (VAR_SET::iterator it = variables.begin();
2250 it != variables.end(); ++it)
2251 if (it->second.is_variable) {
2253 ? it->second.default_iter : n_iter;
2254 gmm::copy(it->second.complex_value[n_iter_i],
2255 gmm::sub_vector(V, it->second.I));
2259 gmm::scaled(V, complex_type(-1)),
2260 brick.cveclist[ind_data][j]);
2264 gmm::scaled(variables[term.var2].complex_value[n_iter_2],
2266 brick.cveclist[ind_data][j]);
2270 model_real_plain_vector V(nbgdof);
2271 for (VAR_SET::iterator it = variables.begin();
2272 it != variables.end(); ++it)
2273 if (it->second.is_variable) {
2275 ? it->second.default_iter : n_iter;
2276 gmm::copy(it->second.real_value[n_iter_i],
2277 gmm::sub_vector(V, it->second.I));
2280 (brick.rmatlist[j], gmm::scaled(V, scalar_type(-1)),
2281 brick.rveclist[ind_data][j]);
2285 gmm::scaled(variables[term.var2].real_value[n_iter_2],
2286 scalar_type(-1)), brick.rveclist[ind_data][j]);
2289 if (term.is_symmetric && term.var1.compare(term.var2)) {
2292 (gmm::conjugated(brick.cmatlist[j]),
2293 gmm::scaled(variables[term.var1].complex_value[n_iter_1],
2295 brick.cveclist_sym[ind_data][j]);
2298 (gmm::transposed(brick.rmatlist[j]),
2299 gmm::scaled(variables[term.var1].real_value[n_iter_1],
2301 brick.rveclist_sym[ind_data][j]);
2308 void model::update_affine_dependent_variables() {
2309 for (VAR_SET::iterator it = variables.begin(); it != variables.end(); ++it)
2310 if (it->second.is_affine_dependent) {
2311 VAR_SET::iterator it2 = variables.find(it->second.org_name);
2312 if (it->second.size() != it2->second.size())
2313 it->second.set_size();
2314 if (it->second.is_complex) {
2315 gmm::add(gmm::scaled(it2->second.complex_value[0],
2316 complex_type(it->second.alpha)),
2317 it->second.affine_complex_value,
2318 it->second.complex_value[0]);
2320 gmm::add(gmm::scaled(it2->second.real_value[0], it->second.alpha),
2321 it->second.affine_real_value, it->second.real_value[0]);
2323 it->second.v_num = std::max(it->second.v_num, it2->second.v_num);
2324 for (
size_type i = 0; i < it->second.n_iter; ++i)
2326 it->second.v_num_data[i] = std::max(it->second.v_num_data[i],
2327 it2->second.v_num_data[i]);
2337 const mesh_fem *mf = pmesh_fem_of_variable(varname);
2338 GMM_ASSERT1(mf,
"Works only with fem variables.");
2342 for (dal::bv_visitor ib(active_bricks); !ib.finished(); ++ib) {
2343 brick_description &brick = bricks[ib];
2345 bool detected =
false;
2346 for (
size_type i = 0; i < brick.vlist.size(); ++i)
2347 if (brick.vlist[i].compare(varname) == 0)
2348 { detected =
true;
break; }
2350 if (detected && brick.mims.size()) {
2352 for (
auto &pmim : brick.mims)
2355 pmim->linked_mesh()));
2356 GMM_ASSERT1(ifo >= 0,
2357 "The given region is only partially covered by " 2358 "region of brick \"" << brick.pbr->brick_name()
2359 <<
"\". Please subdivise the region");
2361 std::string expr = brick.pbr->declare_volume_assembly_string
2362 (*
this, ib, brick.vlist, brick.dlist);
2364 ga_workspace workspace(*
this);
2365 size_type order = workspace.add_expression(expr, dummy_mim, region);
2366 GMM_ASSERT1(order <= 1,
"Wrong order for a Neumann term");
2367 expr = workspace.extract_Neumann_term(varname);
2370 result +=
" + " + workspace.extract_Neumann_term(varname);
2372 result = workspace.extract_Neumann_term(varname);
2387 #if GETFEM_PARA_LEVEL > 1 2388 double t_ref = MPI_Wtime();
2391 context_check();
if (act_size_to_be_done) actualize_sizes();
2393 if (version & BUILD_MATRIX) gmm::clear(cTM);
2394 if (version & BUILD_RHS) gmm::clear(crhs);
2397 if (version & BUILD_MATRIX) gmm::clear(rTM);
2398 if (version & BUILD_RHS) gmm::clear(rrhs);
2400 clear_dof_constraints();
2401 generic_expressions.clear();
2402 update_affine_dependent_variables();
2404 if (version & BUILD_RHS) approx_external_load_ = scalar_type(0);
2406 for (dal::bv_visitor ib(active_bricks); !ib.finished(); ++ib) {
2408 brick_description &brick = bricks[ib];
2411 bool auto_disabled_brick =
true;
2412 for (
size_type j = 0; j < brick.vlist.size(); ++j) {
2413 if (!(is_disabled_variable(brick.vlist[j])))
2414 auto_disabled_brick =
false;
2416 if (auto_disabled_brick)
continue;
2418 update_brick(ib, version);
2420 bool cplx = is_complex() && brick.pbr->is_complex();
2422 scalar_type coeff0 = scalar_type(1);
2423 if (brick.pdispatch) coeff0 = brick.matrix_coeff;
2427 for (
size_type j = 0; j < brick.tlist.size(); ++j) {
2428 term_description &term = brick.tlist[j];
2429 bool isg = term.is_global, isprevious =
false;
2431 scalar_type alpha = coeff0, alpha1 = coeff0, alpha2 = coeff0;
2432 gmm::sub_interval I1(0,nbgdof), I2(0,nbgdof);
2433 VAR_SET::iterator it1, it2;
2435 it1 = variables.find(term.var1);
2436 GMM_ASSERT1(it1->second.is_variable,
"Assembly of data not allowed");
2439 if (term.is_matrix_term && !isg) {
2440 it2 = variables.find(term.var2);
2442 if (!(it2->second.is_variable)) {
2443 std::string vorgname = sup_previous_and_dot_to_varname(term.var2);
2444 VAR_SET::iterator it3 = variables.find(vorgname);
2445 GMM_ASSERT1(it3->second.is_variable,
2446 "Assembly of data not allowed");
2450 alpha *= it1->second.alpha * it2->second.alpha;
2451 alpha1 *= it1->second.alpha;
2452 alpha2 *= it2->second.alpha;
2456 if (term.is_matrix_term && (version & BUILD_MATRIX) && !isprevious
2457 && (isg || (!(it1->second.is_disabled) && !(it2->second.is_disabled)))) {
2458 gmm::add(gmm::scaled(brick.cmatlist[j], alpha),
2459 gmm::sub_matrix(cTM, I1, I2));
2460 if (term.is_symmetric && I1.first() != I2.first()) {
2461 gmm::add(gmm::scaled(gmm::transposed(brick.cmatlist[j]), alpha),
2462 gmm::sub_matrix(cTM, I2, I1));
2465 if (version & BUILD_RHS) {
2466 if (isg || !(it1->second.is_disabled)) {
2467 if (brick.pdispatch) {
2468 for (
size_type k = 0; k < brick.nbrhs; ++k)
2469 gmm::add(gmm::scaled(brick.cveclist[k][j],
2471 gmm::sub_vector(crhs, I1));
2474 gmm::add(gmm::scaled(brick.cveclist[0][j],
2475 complex_type(alpha1)),
2476 gmm::sub_vector(crhs, I1));
2479 if (term.is_matrix_term && brick.pbr->is_linear() && is_linear()) {
2480 if (it2->second.is_affine_dependent
2481 && !(it1->second.is_disabled))
2482 gmm::mult_add(brick.cmatlist[j],
2483 gmm::scaled(it2->second.affine_complex_value,
2484 complex_type(-alpha1)),
2485 gmm::sub_vector(crhs, I1));
2486 if (term.is_symmetric && I1.first() != I2.first()
2487 && it1->second.is_affine_dependent
2488 && !(it2->second.is_disabled)) {
2489 gmm::mult_add(gmm::conjugated(brick.cmatlist[j]),
2490 gmm::scaled(it1->second.affine_complex_value,
2491 complex_type(-alpha2)),
2492 gmm::sub_vector(crhs, I2));
2495 if (term.is_matrix_term && brick.pbr->is_linear()
2496 && (!is_linear() || (version & BUILD_WITH_COMPLETE_RHS))) {
2497 if (!(it1->second.is_disabled))
2498 gmm::mult_add(brick.cmatlist[j],
2499 gmm::scaled(it2->second.complex_value[0],
2500 complex_type(-alpha1)),
2501 gmm::sub_vector(crhs, I1));
2503 if (term.is_symmetric && I1.first() != I2.first() &&
2504 !(it2->second.is_disabled)) {
2505 if (brick.pdispatch) {
2506 for (
size_type k = 0; k < brick.nbrhs; ++k)
2507 gmm::add(gmm::scaled(brick.cveclist_sym[k][j],
2509 gmm::sub_vector(crhs, I2));
2511 gmm::add(gmm::scaled(brick.cveclist_sym[0][j],
2512 complex_type(alpha2)),
2513 gmm::sub_vector(crhs, I2));
2515 if (brick.pbr->is_linear()
2516 && (!is_linear() || (version & BUILD_WITH_COMPLETE_RHS))) {
2517 gmm::mult_add(gmm::conjugated(brick.cmatlist[j]),
2518 gmm::scaled(it1->second.complex_value[0],
2519 complex_type(-alpha2)),
2520 gmm::sub_vector(crhs, I2));
2524 }
else if (is_complex()) {
2525 if (term.is_matrix_term && (version & BUILD_MATRIX) && !isprevious
2526 && (isg || (!(it1->second.is_disabled) && !(it2->second.is_disabled)))) {
2527 gmm::add(gmm::scaled(brick.rmatlist[j], alpha),
2528 gmm::sub_matrix(cTM, I1, I2));
2529 if (term.is_symmetric && I1.first() != I2.first()) {
2530 gmm::add(gmm::scaled(gmm::transposed(brick.rmatlist[j]), alpha),
2531 gmm::sub_matrix(cTM, I2, I1));
2534 if (version & BUILD_RHS) {
2535 if (isg || !(it1->second.is_disabled)) {
2536 if (brick.pdispatch) {
2537 for (
size_type k = 0; k < brick.nbrhs; ++k)
2538 gmm::add(gmm::scaled(brick.rveclist[k][j],
2540 gmm::sub_vector(crhs, I1));
2543 gmm::add(gmm::scaled(brick.rveclist[0][j], alpha1),
2544 gmm::sub_vector(crhs, I1));
2547 if (term.is_matrix_term && brick.pbr->is_linear() && is_linear()) {
2548 if (it2->second.is_affine_dependent
2549 && !(it1->second.is_disabled))
2550 gmm::mult_add(brick.rmatlist[j],
2551 gmm::scaled(it2->second.affine_complex_value,
2552 complex_type(-alpha1)),
2553 gmm::sub_vector(crhs, I1));
2554 if (term.is_symmetric && I1.first() != I2.first()
2555 && it1->second.is_affine_dependent
2556 && !(it2->second.is_disabled)) {
2557 gmm::mult_add(gmm::transposed(brick.rmatlist[j]),
2558 gmm::scaled(it1->second.affine_complex_value,
2559 complex_type(-alpha2)),
2560 gmm::sub_vector(crhs, I2));
2563 if (term.is_matrix_term && brick.pbr->is_linear()
2564 && (!is_linear() || (version & BUILD_WITH_COMPLETE_RHS))) {
2565 if (!(it1->second.is_disabled))
2566 gmm::mult_add(brick.rmatlist[j],
2567 gmm::scaled(it2->second.complex_value[0],
2568 complex_type(-alpha1)),
2569 gmm::sub_vector(crhs, I1));
2571 if (term.is_symmetric && I1.first() != I2.first() &&
2572 !(it2->second.is_disabled)) {
2573 if (brick.pdispatch) {
2574 for (
size_type k = 0; k < brick.nbrhs; ++k)
2575 gmm::add(gmm::scaled(brick.rveclist_sym[k][j],
2577 gmm::sub_vector(crhs, I2));
2580 gmm::add(gmm::scaled(brick.rveclist_sym[0][j], alpha2),
2581 gmm::sub_vector(crhs, I2));
2583 if (brick.pbr->is_linear()
2584 && (!is_linear() || (version & BUILD_WITH_COMPLETE_RHS))) {
2585 gmm::mult_add(gmm::transposed(brick.rmatlist[j]),
2586 gmm::scaled(it1->second.complex_value[0],
2587 complex_type(-alpha2)),
2588 gmm::sub_vector(crhs, I2));
2593 if (term.is_matrix_term && (version & BUILD_MATRIX) && !isprevious
2594 && (isg || (!(it1->second.is_disabled)
2595 && !(it2->second.is_disabled)))) {
2596 gmm::add(gmm::scaled(brick.rmatlist[j], alpha),
2597 gmm::sub_matrix(rTM, I1, I2));
2598 if (term.is_symmetric && I1.first() != I2.first()) {
2599 gmm::add(gmm::scaled(gmm::transposed(brick.rmatlist[j]), alpha),
2600 gmm::sub_matrix(rTM, I2, I1));
2603 if (version & BUILD_RHS) {
2604 if (isg || !(it1->second.is_disabled)) {
2605 if (brick.pdispatch) {
2606 for (
size_type k = 0; k < brick.nbrhs; ++k)
2607 gmm::add(gmm::scaled(brick.rveclist[k][j],
2609 gmm::sub_vector(rrhs, I1));
2612 gmm::add(gmm::scaled(brick.rveclist[0][j], alpha1),
2613 gmm::sub_vector(rrhs, I1));
2616 if (term.is_matrix_term && brick.pbr->is_linear() && is_linear()) {
2617 if (it2->second.is_affine_dependent
2618 && !(it1->second.is_disabled))
2619 gmm::mult_add(brick.rmatlist[j],
2620 gmm::scaled(it2->second.affine_real_value,
2622 gmm::sub_vector(rrhs, I1));
2623 if (term.is_symmetric && I1.first() != I2.first()
2624 && it1->second.is_affine_dependent
2625 && !(it2->second.is_disabled)) {
2626 gmm::mult_add(gmm::transposed(brick.rmatlist[j]),
2627 gmm::scaled(it1->second.affine_real_value,
2629 gmm::sub_vector(rrhs, I2));
2632 if (term.is_matrix_term && brick.pbr->is_linear()
2633 && (!is_linear() || (version & BUILD_WITH_COMPLETE_RHS))) {
2634 if (!(it1->second.is_disabled))
2635 gmm::mult_add(brick.rmatlist[j],
2636 gmm::scaled(it2->second.real_value[0],
2638 gmm::sub_vector(rrhs, I1));
2640 if (term.is_symmetric && I1.first() != I2.first() &&
2641 !(it2->second.is_disabled)) {
2642 if (brick.pdispatch) {
2643 for (
size_type k = 0; k < brick.nbrhs; ++k)
2644 gmm::add(gmm::scaled(brick.rveclist_sym[k][j],
2646 gmm::sub_vector(rrhs, I2));
2649 gmm::add(gmm::scaled(brick.rveclist_sym[0][j], alpha2),
2650 gmm::sub_vector(rrhs, I2));
2652 if (brick.pbr->is_linear()
2653 && (!is_linear() || (version & BUILD_WITH_COMPLETE_RHS))) {
2654 gmm::mult_add(gmm::transposed(brick.rmatlist[j]),
2655 gmm::scaled(it1->second.real_value[0], -alpha2),
2656 gmm::sub_vector(rrhs, I2));
2663 if (brick.pbr->is_linear())
2664 brick.terms_to_be_computed =
false;
2677 if (version & BUILD_RHS) approx_external_load_ += brick.external_load;
2681 if (generic_expressions.size()) {
2682 model_real_plain_vector residual;
2683 if (version & BUILD_RHS) gmm::resize(residual, gmm::vect_size(rrhs));
2691 open_mp_is_running_properly check;
2693 #pragma omp parallel default(shared) 2697 if (version & BUILD_RHS)
2698 GMM_TRACE2(
"Global generic assembly RHS");
2699 if (version & BUILD_MATRIX)
2700 GMM_TRACE2(
"Global generic assembly tangent term");
2702 ga_workspace workspace(*
this);
2704 for (
const auto &ad : assignments)
2705 workspace.add_assignment_expression
2706 (ad.varname, ad.expr, ad.region, ad.order, ad.before);
2708 for (
const auto &ge : generic_expressions)
2709 workspace.add_expression(ge.expr, ge.mim, ge.region);
2711 if (version & BUILD_RHS) {
2713 GMM_ASSERT1(
false,
"to be done");
2715 workspace.set_assembled_vector(residual_distributed);
2716 workspace.assembly(1);
2720 if (version & BUILD_MATRIX) {
2722 GMM_ASSERT1(
false,
"to be done");
2724 workspace.set_assembled_matrix(tangent_matrix_distributed);
2725 workspace.assembly(2);
2730 exception.rethrow();
2733 if (version & BUILD_RHS) gmm::add(gmm::scaled(residual, scalar_type(-1)), rrhs);
2738 if ((version & BUILD_RHS) || (version & BUILD_MATRIX)) {
2740 std::vector<size_type> dof_indices;
2741 std::vector<complex_type> dof_pr_values;
2742 std::vector<complex_type> dof_go_values;
2743 for (
const auto &keyval : complex_dof_constraints) {
2744 const gmm::sub_interval &I = interval_of_variable(keyval.first);
2745 const model_complex_plain_vector &V = complex_variable(keyval.first);
2746 for (
const auto &val : keyval.second) {
2747 dof_indices.push_back(val.first + I.first());
2748 dof_go_values.push_back(val.second);
2749 dof_pr_values.push_back(V[val.first]);
2753 if (dof_indices.size()) {
2754 gmm::sub_index SI(dof_indices);
2755 gmm::sub_interval II(0, nb_dof());
2757 if (version & BUILD_RHS) {
2758 if (MPI_IS_MASTER())
2759 approx_external_load_ += gmm::vect_norm1(dof_go_values);
2761 if (is_symmetric_) {
2762 scalar_type valnorm = gmm::vect_norm2(dof_go_values);
2763 if (valnorm > scalar_type(0)) {
2764 GMM_ASSERT1(version & BUILD_MATRIX,
"Rhs only for a " 2765 "symmetric linear problem with dof " 2766 "constraint not allowed");
2767 model_complex_plain_vector vv(gmm::vect_size(crhs));
2768 gmm::mult(gmm::sub_matrix(cTM, II, SI), dof_go_values, vv);
2770 gmm::add(gmm::scaled(vv, scalar_type(-1)), crhs);
2773 gmm::copy(dof_go_values, gmm::sub_vector(crhs, SI));
2775 gmm::add(dof_go_values,
2776 gmm::scaled(dof_pr_values, complex_type(-1)),
2777 gmm::sub_vector(crhs, SI));
2780 if (version & BUILD_MATRIX) {
2781 gmm::clear(gmm::sub_matrix(cTM, SI, II));
2782 if (is_symmetric_) gmm::clear(gmm::sub_matrix(cTM, II, SI));
2784 if (MPI_IS_MASTER()) {
2785 for (
size_type i = 0; i < dof_indices.size(); ++i)
2786 cTM(dof_indices[i], dof_indices[i]) = complex_type(1);
2791 std::vector<size_type> dof_indices;
2792 std::vector<scalar_type> dof_pr_values;
2793 std::vector<scalar_type> dof_go_values;
2794 for (
const auto &keyval : real_dof_constraints) {
2795 const gmm::sub_interval &I = interval_of_variable(keyval.first);
2796 const model_real_plain_vector &V = real_variable(keyval.first);
2797 for (
const auto &val : keyval.second) {
2798 dof_indices.push_back(val.first + I.first());
2799 dof_go_values.push_back(val.second);
2800 dof_pr_values.push_back(V[val.first]);
2804 #if GETFEM_PARA_LEVEL > 1 2805 GMM_ASSERT1(MPI_IS_MASTER() || (dof_indices.size() == 0),
2806 "Sorry, for the moment, the dof constraints have to be " 2807 "added on the master process only");
2808 size_type dof_indices_size = dof_indices.size();
2809 MPI_BCAST0_SCALAR(dof_indices_size);
2810 dof_indices.resize(dof_indices_size);
2811 MPI_BCAST0_VECTOR(dof_indices);
2812 dof_pr_values.resize(dof_indices_size);
2813 MPI_BCAST0_VECTOR(dof_pr_values);
2814 dof_go_values.resize(dof_indices_size);
2815 MPI_BCAST0_VECTOR(dof_go_values);
2818 if (dof_indices.size()) {
2819 gmm::sub_index SI(dof_indices);
2820 gmm::sub_interval II(0, nb_dof());
2822 if (version & BUILD_RHS) {
2823 if (MPI_IS_MASTER())
2824 approx_external_load_ += gmm::vect_norm1(dof_go_values);
2826 if (is_symmetric_) {
2827 scalar_type valnorm = gmm::vect_norm2(dof_go_values);
2828 if (valnorm > scalar_type(0)) {
2829 GMM_ASSERT1(version & BUILD_MATRIX,
"Rhs only for a " 2830 "symmetric linear problem with dof " 2831 "constraint not allowed");
2832 model_real_plain_vector vv(gmm::vect_size(rrhs));
2833 gmm::mult(gmm::sub_matrix(rTM, II, SI), dof_go_values, vv);
2835 gmm::add(gmm::scaled(vv, scalar_type(-1)), rrhs);
2838 gmm::copy(dof_go_values, gmm::sub_vector(rrhs, SI));
2840 gmm::add(dof_go_values,
2841 gmm::scaled(dof_pr_values, scalar_type(-1)),
2842 gmm::sub_vector(rrhs, SI));
2845 if (version & BUILD_MATRIX) {
2846 gmm::clear(gmm::sub_matrix(rTM, SI, II));
2847 if (is_symmetric_) gmm::clear(gmm::sub_matrix(rTM, II, SI));
2849 if (MPI_IS_MASTER()) {
2850 for (
size_type i = 0; i < dof_indices.size(); ++i)
2851 rTM(dof_indices[i], dof_indices[i]) = scalar_type(1);
2858 if (version & BUILD_RHS) {
2859 approx_external_load_ = MPI_SUM_SCALAR(approx_external_load_);
2863 #if GETFEM_PARA_LEVEL > 1 2865 if (MPI_IS_MASTER()) cout <<
"Assembly time " << MPI_Wtime()-t_ref << endl;
2874 return it->second.associated_mf();
2880 return it->second.passociated_mf();
2884 model::qdims_of_variable(
const std::string &name)
const {
2886 const mesh_fem *mf = it->second.passociated_mf();
2887 const im_data *imd = it->second.pim_data;
2890 bgeot::multi_index mi = mf->get_qdims();
2891 if (n > 1 || it->second.qdims.size() > 1) {
2893 if (mi.back() == 1) { mi.back() *= it->second.qdims[0]; ++i; }
2894 for (; i < it->second.qdims.size(); ++i)
2895 mi.push_back(it->second.qdims[i]);
2899 bgeot::multi_index mi = imd->tensor_size();
2902 "Invalid mesh im data vector");
2903 if (n > 1 || it->second.qdims.size() > 1) {
2905 if (mi.back() == 1) { mi.back() *= it->second.qdims[0]; ++i; }
2906 for (; i < it->second.qdims.size(); ++i)
2907 mi.push_back(it->second.qdims[i]);
2911 return it->second.qdims;
2914 size_type model::qdim_of_variable(
const std::string &name)
const {
2916 const mesh_fem *mf = it->second.passociated_mf();
2917 const im_data *imd = it->second.pim_data;
2922 return imd->tensor_size().total_size() * n;
2928 const gmm::sub_interval &
2929 model::interval_of_variable(
const std::string &name)
const {
2931 if (act_size_to_be_done) actualize_sizes();
2932 VAR_SET::const_iterator it = find_variable(name);
2933 return it->second.I;
2936 const model_real_plain_vector &
2939 else return real_variable(name,
size_type(-1));
2942 const model_real_plain_vector &
2944 GMM_ASSERT1(!complex_version,
"This model is a complex one");
2945 GMM_ASSERT1(!
is_old(name),
"Please don't use Old_ prefix in combination with" 2946 " variable version");
2948 auto it = variables.find(name);
2949 GMM_ASSERT1(it!=variables.end(),
"Undefined variable " << name);
2950 if (act_size_to_be_done && it->second.is_fem_dofs) {
2951 if (it->second.filter != VDESCRFILTER_NO)
2954 it->second.set_size();
2956 if (niter ==
size_type(-1)) niter = it->second.default_iter;
2957 GMM_ASSERT1(it->second.n_iter + it->second.n_temp_iter > niter,
2958 "Invalid iteration number " << niter <<
" for " << name);
2959 return it->second.real_value[niter];
2962 const model_complex_plain_vector &
2965 else return complex_variable(name,
size_type(-1));
2968 const model_complex_plain_vector &
2970 GMM_ASSERT1(complex_version,
"This model is a real one");
2971 GMM_ASSERT1(!
is_old(name),
"Please don't use Old_ prefix in combination with" 2972 " variable version");
2974 auto it = variables.find(name);
2975 GMM_ASSERT1(it!=variables.end(),
"Undefined variable " << name);
2976 if (act_size_to_be_done && it->second.is_fem_dofs) {
2977 if (it->second.filter != VDESCRFILTER_NO)
2980 it->second.set_size();
2982 if (niter ==
size_type(-1)) niter = it->second.default_iter;
2983 GMM_ASSERT1(it->second.n_iter + it->second.n_temp_iter > niter,
2984 "Invalid iteration number " 2985 << niter <<
" for " << name);
2986 return it->second.complex_value[niter];
2989 model_real_plain_vector &
2992 else return set_real_variable(name,
size_type(-1));
2996 model_real_plain_vector &
2998 GMM_ASSERT1(!complex_version,
"This model is a complex one");
2999 GMM_ASSERT1(!
is_old(name),
"Please don't use Old_ prefix in combination with" 3000 " variable version");
3002 auto it = variables.find(name);
3003 GMM_ASSERT1(it!=variables.end(),
"Undefined variable " << name);
3004 if (act_size_to_be_done && it->second.is_fem_dofs) {
3005 if (it->second.filter != VDESCRFILTER_NO)
3008 it->second.set_size();
3010 if (niter ==
size_type(-1)) niter = it->second.default_iter;
3011 it->second.v_num_data[niter] = act_counter();
3012 GMM_ASSERT1(it->second.n_iter + it->second.n_temp_iter > niter,
3013 "Invalid iteration number " 3014 << niter <<
" for " << name);
3015 return it->second.real_value[niter];
3018 model_complex_plain_vector &
3021 else return set_complex_variable(name,
size_type(-1));
3024 model_complex_plain_vector &
3026 GMM_ASSERT1(complex_version,
"This model is a real one");
3027 GMM_ASSERT1(!
is_old(name),
"Please don't use Old_ prefix in combination with" 3028 " variable version");
3030 auto it = variables.find(name);
3031 GMM_ASSERT1(it!=variables.end(),
"Undefined variable " << name);
3032 if (act_size_to_be_done && it->second.is_fem_dofs) {
3033 if (it->second.filter != VDESCRFILTER_NO)
3036 it->second.set_size();
3038 if (niter ==
size_type(-1)) niter = it->second.default_iter;
3039 it->second.v_num_data[niter] = act_counter();
3040 GMM_ASSERT1(it->second.n_iter + it->second.n_temp_iter > niter,
3041 "Invalid iteration number " 3042 << niter <<
" for " << name);
3043 return it->second.complex_value[niter];
3046 model_real_plain_vector &
3047 model::set_real_constant_part(
const std::string &name)
const {
3048 GMM_ASSERT1(!complex_version,
"This model is a complex one");
3050 VAR_SET::iterator it = variables.find(name);
3051 GMM_ASSERT1(it != variables.end(),
"Undefined variable " << name);
3052 GMM_ASSERT1(it->second.is_affine_dependent,
3053 "Only for affine dependent variables");
3054 if (act_size_to_be_done && it->second.is_fem_dofs) {
3055 if (it->second.filter != VDESCRFILTER_NO)
3058 it->second.set_size();
3060 for (
auto &v_num : it->second.v_num_data) v_num = act_counter();
3061 return it->second.affine_real_value;
3064 model_complex_plain_vector &
3065 model::set_complex_constant_part(
const std::string &name)
const {
3066 GMM_ASSERT1(complex_version,
"This model is a real one");
3068 VAR_SET::iterator it = variables.find(name);
3069 GMM_ASSERT1(it!=variables.end(),
"Undefined variable " << name);
3070 if (act_size_to_be_done && it->second.is_fem_dofs) {
3071 if (it->second.filter != VDESCRFILTER_NO)
3074 it->second.set_size();
3076 for (
auto &v_num : it->second.v_num_data) v_num = act_counter();
3077 return it->second.affine_complex_value;
3082 const brick_description &brick = bricks[ind_brick];
3083 update_brick(ind_brick, model::BUILD_ALL);
3085 brick.pbr->check_stiffness_matrix_and_rhs(*
this, ind_brick, brick.tlist,
3086 brick.vlist, brick.dlist, brick.mims, brick.rmatlist,
3087 brick.rveclist[0], brick.rveclist_sym[0], brick.region);
3090 void model::clear() {
3092 active_bricks.clear();
3093 valid_bricks.clear();
3094 real_dof_constraints.clear();
3095 complex_dof_constraints.clear();
3097 rTM = model_real_sparse_matrix();
3098 cTM = model_complex_sparse_matrix();
3099 rrhs = model_real_plain_vector();
3100 crhs = model_complex_plain_vector();
3105 void virtual_brick::full_asm_real_tangent_terms_(
const model &md,
size_type ind_brick,
3106 const model::varnamelist &term_list,
3107 const model::varnamelist &var_list,
3108 const model::mimlist &mim_list,
3109 model::real_matlist &rmatlist,
3110 model::real_veclist &rveclist,
3111 model::real_veclist &rveclist_sym,
3112 size_type region, build_version version)
const 3114 real_pre_assembly_in_serial(md, ind_brick, term_list, var_list, mim_list, rmatlist,
3115 rveclist, rveclist_sym, region, version);
3116 asm_real_tangent_terms(md, ind_brick, term_list, var_list, mim_list, rmatlist,
3117 rveclist, rveclist_sym, region, version);
3118 real_post_assembly_in_serial(md, ind_brick, term_list, var_list, mim_list, rmatlist,
3119 rveclist, rveclist_sym, region, version);
3124 const model::termlist& tlist,
3125 const model::varnamelist &vl,
3126 const model::varnamelist &dl,
3127 const model::mimlist &mims,
3128 model::real_matlist &matl,
3129 model::real_veclist &rvc1,
3130 model::real_veclist &rvc2,
3132 const scalar_type TINY)
const 3134 std::cout<<
"******Verifying stiffnesses of *******"<<std::endl;
3135 std::cout<<
"*** "<<brick_name()<<std::endl;
3138 std::map<std::string,size_type> rhs_index;
3139 for(
size_type iterm=0;iterm<matl.size();iterm++)
3140 if (tlist[iterm].var1==tlist[iterm].var2) rhs_index[tlist[iterm].var1]=iterm;
3142 if (rhs_index.size()==0){
3143 GMM_WARNING0(
"*** cannot verify stiffness for this brick***");
3146 full_asm_real_tangent_terms_(md, s, vl, dl, mims, matl, rvc1, rvc2,
3147 rg, model::BUILD_MATRIX);
3148 for(
size_type iterm=0;iterm<matl.size();iterm++)
3151 std::cout<<std::endl;
3152 std::cout<<
" Stiffness["<<tlist[iterm].var1
3153 <<
","<<tlist[iterm].var2<<
"]:"<<std::endl;
3156 std::cout<<
" "<<tlist[iterm].var1<<
" has zero size. Skipping this term"<<std::endl;
3161 std::cout<<
" "<<tlist[iterm].var2<<
" has zero size. Skipping this term"<<std::endl;
3165 model_real_sparse_matrix SM(matl[iterm]);
3166 gmm::fill(rvc1[rhs_index[tlist[iterm].var1]], 0.0);
3167 full_asm_real_tangent_terms_(md, s, vl, dl, mims, matl, rvc1, rvc2,
3168 rg, model::BUILD_RHS);
3169 if (gmm::mat_euclidean_norm(matl[iterm])<1e-12){
3170 std::cout<<
" The assembled matrix is nearly zero, skipping."<<std::endl;
3173 model_real_plain_vector RHS0(rvc1[rhs_index[tlist[iterm].var1]]);
3176 model_real_sparse_matrix fdSM(matl[iterm].nrows(), matl[iterm].ncols());
3178 model_real_plain_vector& RHS1 = rvc1[rhs_index[tlist[iterm].var1]];
3180 scalar_type relative_tiny = gmm::vect_norminf(RHS1)*TINY;
3181 if (relative_tiny < TINY) relative_tiny = TINY;
3183 for (
size_type j = 0; j < matl[iterm].ncols(); j++){
3184 U[j] += relative_tiny;
3185 gmm::fill(RHS1, 0.0);
3186 full_asm_real_tangent_terms_(md, s, vl, dl, mims, matl, rvc1, rvc2,
3187 rg, model::BUILD_RHS);
3188 for (
size_type i = 0; i<matl[iterm].nrows(); i++)
3189 fdSM(i, j) = (RHS0[i] - RHS1[i]) / relative_tiny;
3190 U[j] -= relative_tiny;
3193 model_real_sparse_matrix diffSM(matl[iterm].nrows(),matl[iterm].ncols());
3194 gmm::add(SM,gmm::scaled(fdSM,-1.0),diffSM);
3195 scalar_type norm_error_euc
3196 = gmm::mat_euclidean_norm(diffSM)/gmm::mat_euclidean_norm(SM)*100;
3197 scalar_type norm_error_1
3198 = gmm::mat_norm1(diffSM)/gmm::mat_norm1(SM)*100;
3199 scalar_type norm_error_max
3200 = gmm::mat_maxnorm(diffSM)/gmm::mat_maxnorm(SM)*100;
3203 scalar_type nsym_norm_error_euc=0.0;
3204 scalar_type nsym_norm_error_1=0.0;
3205 scalar_type nsym_norm_error_max=0.0;
3206 if (tlist[iterm].var1==tlist[iterm].var2){
3207 model_real_sparse_matrix diffSMtransposed(matl[iterm].nrows(),matl[iterm].ncols());
3208 gmm::add(gmm::transposed(fdSM),gmm::scaled(fdSM,-1.0),diffSMtransposed);
3210 = gmm::mat_euclidean_norm(diffSMtransposed)/gmm::mat_euclidean_norm(fdSM)*100;
3212 = gmm::mat_norm1(diffSMtransposed)/gmm::mat_norm1(fdSM)*100;
3214 = gmm::mat_maxnorm(diffSMtransposed)/gmm::mat_maxnorm(fdSM)*100;
3218 if(rvc1[0].size()<8){
3219 std::cout <<
"RHS Stiffness Matrix: \n";
3220 std::cout <<
"------------------------\n";
3221 for(
size_type i=0; i < rvc1[iterm].size(); ++i){
3223 for(
size_type j=0; j < rvc1[iterm].size(); ++j){
3224 std::cout << fdSM(i,j) <<
" ";
3228 std::cout <<
"Analytical Stiffness Matrix: \n";
3229 std::cout <<
"------------------------\n";
3230 for(
size_type i=0; i < rvc1[iterm].size(); ++i){
3232 for(
size_type j=0; j < rvc1[iterm].size(); ++j){
3233 std::cout << matl[iterm](i,j) <<
" ";
3237 std::cout <<
"Vector U: \n";
3238 std::cout <<
"------------------------\n";
3239 for(
size_type i=0; i < rvc1[iterm].size(); ++i){
3246 <<
"\n\nfinite diff test error_norm_eucl: " << norm_error_euc <<
"%\n" 3247 <<
"finite diff test error_norm1: " << norm_error_1 <<
"%\n" 3248 <<
"finite diff test error_max_norm: " << norm_error_max <<
"%\n\n\n";
3250 if (tlist[iterm].var1==tlist[iterm].var2){
3252 <<
"Nonsymmetrical test error_norm_eucl: "<< nsym_norm_error_euc<<
"%\n" 3253 <<
"Nonsymmetrical test error_norm1: " << nsym_norm_error_1 <<
"%\n" 3254 <<
"Nonsymmetrical test error_max_norm: " << nsym_norm_error_max <<
"%" 3274 struct gen_source_term_assembly_brick :
public virtual_brick {
3276 std::string expr, directvarname, directdataname;
3277 model::varnamelist vl_test1;
3280 const model::varnamelist &,
3281 const model::varnamelist &,
3282 const model::mimlist &mims,
3283 model::real_matlist &,
3284 model::real_veclist &vecl,
3285 model::real_veclist &,
3287 build_version)
const override {
3288 GMM_ASSERT1(vecl.size() == vl_test1.size()
3289 + ((directdataname.size() == 0) ? 0 : 1),
"Wrong number " 3290 "of terms for Generic source term assembly brick ");
3291 GMM_ASSERT1(mims.size() == 1,
"Generic source term assembly brick " 3292 "needs one and only one mesh_im");
3293 GMM_TRACE2(
"Generic source term assembly");
3295 gmm::clear(vecl[0]);
3299 ga_workspace workspace(md,
true);
3300 GMM_TRACE2(name <<
": generic source term assembly");
3301 workspace.add_expression(expr, *(mims[0]), region);
3302 model::varnamelist vlmd; md.variable_list(vlmd);
3303 for (
size_type i = 0; i < vlmd.size(); ++i)
3304 if (md.is_disabled_variable(vlmd[i]))
3305 nbgdof = std::max(nbgdof,
3306 workspace.interval_of_variable(vlmd[i]).last());
3307 GMM_TRACE2(name <<
": generic matrix assembly");
3308 model_real_plain_vector V(nbgdof);
3309 workspace.set_assembled_vector(V);
3310 workspace.assembly(1);
3311 for (
size_type i = 0; i < vl_test1.size(); ++i) {
3312 gmm::copy(gmm::sub_vector
3313 (V, workspace.interval_of_variable(vl_test1[i])), vecl[i]);
3317 if (directvarname.size()) {
3323 const model::varnamelist &,
3324 const model::varnamelist &,
3325 const model::mimlist &,
3326 model::real_matlist &,
3327 model::real_veclist &vecl,
3328 model::real_veclist &,
3330 build_version)
const override {
3331 scalar_type el = scalar_type(0);
3332 for (
size_type i=0; i < vecl.size(); ++i) el += gmm::vect_norm1(vecl[i]);
3333 md.add_external_load(ib, el);
3336 virtual std::string declare_volume_assembly_string
3338 const model::varnamelist &)
const {
3339 return std::string();
3342 gen_source_term_assembly_brick(
const std::string &expr_,
3343 std::string brickname,
3344 const model::varnamelist &vl_test1_,
3345 const std::string &directvarname_,
3346 const std::string &directdataname_)
3347 : vl_test1(vl_test1_) {
3348 if (brickname.size() == 0)
3349 brickname =
"Generic source term assembly brick";
3351 set_flags(brickname,
true ,
3355 directvarname = directvarname_; directdataname = directdataname_;
3360 static bool check_compatibility_vl_test(
model &md,
const model::varnamelist vl_test) {
3361 model::varnamelist org;
3362 for (
size_type i = 0; i < vl_test.size(); ++i) {
3363 if (md.is_affine_dependent_variable(vl_test[i]))
3364 org.push_back(md.org_variable(vl_test[i]));
3366 for (
size_type i = 0; i < vl_test.size(); ++i)
3367 for (
size_type j = 0; j < org.size(); ++j)
3368 if (vl_test[i].compare(org[j]) == 0)
return false;
3374 std::string brickname, std::string directvarname,
3375 const std::string &directdataname,
bool return_if_nonlin) {
3377 ga_workspace workspace(md);
3378 size_type order = workspace.add_expression(expr, mim, region);
3379 GMM_ASSERT1(order <= 1,
"Wrong order for a source term");
3380 model::varnamelist vl, vl_test1, vl_test2, dl;
3381 bool is_lin = workspace.used_variables(vl, vl_test1, vl_test2, dl, 1);
3382 if (!is_lin && return_if_nonlin)
return size_type(-1);
3383 GMM_ASSERT1(is_lin,
"Nonlinear term");
3384 GMM_ASSERT1(check_compatibility_vl_test(md, vl_test1),
3385 "This brick do not support the assembly on both an affine " 3386 "dependent variable and its original variable. " 3387 "Split the brick.");
3389 if (directdataname.size()) {
3390 vl.push_back(directvarname);
3391 dl.push_back(directdataname);
3392 }
else directvarname =
"";
3394 pbrick pbr = std::make_shared<gen_source_term_assembly_brick>
3395 (expr, brickname, vl_test1, directvarname, directdataname);
3398 for (
size_type i = 0; i < vl_test1.size(); ++i)
3399 tl.push_back(model::term_description(vl_test1[i]));
3400 if (directdataname.size())
3401 tl.push_back(model::term_description(directvarname));
3403 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
3416 model::varnamelist vl_test1, vl_test2;
3418 virtual void asm_real_tangent_terms(
const model &md,
size_type ib,
3419 const model::varnamelist &,
3420 const model::varnamelist &dl,
3421 const model::mimlist &mims,
3422 model::real_matlist &matl,
3423 model::real_veclist &,
3424 model::real_veclist &,
3426 build_version version)
const {
3427 GMM_ASSERT1(matl.size() == vl_test1.size(),
3428 "Wrong number of terms for Generic linear assembly brick");
3429 GMM_ASSERT1(mims.size() == 1,
3430 "Generic linear assembly brick needs one and only one " 3432 bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0);
3433 for (
size_type i = 0; i < dl.size(); ++i)
3434 recompute_matrix = recompute_matrix ||
3435 md.is_var_newer_than_brick(dl[i], ib);
3437 if (recompute_matrix) {
3439 ga_workspace workspace(md,
true);
3440 workspace.add_expression(expr, *(mims[0]), region);
3441 model::varnamelist vlmd; md.variable_list(vlmd);
3442 for (
size_type i = 0; i < vlmd.size(); ++i)
3443 if (md.is_disabled_variable(vlmd[i]))
3444 nbgdof = std::max(nbgdof,
3445 workspace.interval_of_variable(vlmd[i]).last());
3446 GMM_TRACE2(name <<
": generic matrix assembly");
3447 model_real_sparse_matrix R(nbgdof, nbgdof);
3448 workspace.set_assembled_matrix(R);
3449 workspace.assembly(2);
3450 for (
size_type i = 0; i < vl_test1.size(); ++i) {
3451 scalar_type alpha = scalar_type(1)
3452 / ( workspace.factor_of_variable(vl_test1[i]) *
3453 workspace.factor_of_variable(vl_test2[i]));
3454 gmm::copy(gmm::scaled(gmm::sub_matrix
3455 (R, workspace.interval_of_variable(vl_test1[i]),
3456 workspace.interval_of_variable(vl_test2[i])), alpha),
3462 virtual std::string declare_volume_assembly_string
3464 const model::varnamelist &)
const {
3465 return is_lower_dim ? std::string() : expr;
3468 gen_linear_assembly_brick(
const std::string &expr_,
const mesh_im &mim,
3470 bool is_coer, std::string brickname,
3471 const model::varnamelist &vl_test1_,
3472 const model::varnamelist &vl_test2_)
3473 : vl_test1(vl_test1_), vl_test2(vl_test2_) {
3474 if (brickname.size() == 0) brickname =
"Generic linear assembly brick";
3476 is_lower_dim = mim.is_lower_dimensional();
3477 set_flags(brickname,
true ,
3484 static bool check_compatibility_vl_test(
model &md,
3485 const model::varnamelist vl_test1,
3486 const model::varnamelist vl_test2) {
3487 for (
size_type i = 0; i < vl_test1.size(); ++i)
3488 for (
size_type j = 0; j < vl_test1.size(); ++j) {
3489 bool is1 = md.is_affine_dependent_variable(vl_test1[i]);
3490 bool is2 = md.is_affine_dependent_variable(vl_test2[i]);
3492 const std::string &org1
3493 = is1 ? md.org_variable(vl_test1[i]) : vl_test1[i];
3494 const std::string &org2
3495 = is2 ? md.org_variable(vl_test2[i]) : vl_test2[i];
3496 bool is1_bis = md.is_affine_dependent_variable(vl_test1[j]);
3497 bool is2_bis = md.is_affine_dependent_variable(vl_test2[j]);
3498 const std::string &org1_bis = is1_bis ? md.org_variable(vl_test1[j])
3500 const std::string &org2_bis = is2_bis ? md.org_variable(vl_test2[j])
3502 if (org1.compare(org1_bis) == 0 && org2.compare(org2_bis))
3511 bool is_sym,
bool is_coercive, std::string brickname,
3512 bool return_if_nonlin) {
3514 ga_workspace workspace(md,
true);
3515 size_type order = workspace.add_expression(expr, mim, region);
3516 model::varnamelist vl, vl_test1, vl_test2, dl;
3517 bool is_lin = workspace.used_variables(vl, vl_test1, vl_test2, dl, 2);
3519 if (!is_lin && return_if_nonlin)
return size_type(-1);
3520 GMM_ASSERT1(is_lin,
"Nonlinear term");
3521 if (order == 0) { is_coercive = is_sym =
true; }
3523 std::string const_expr= workspace.extract_constant_term(mim.
linked_mesh());
3524 if (const_expr.size()) {
3525 add_source_term_generic_assembly_brick
3526 (md, mim, const_expr, region, brickname+
" (source term)");
3531 GMM_ASSERT1(check_compatibility_vl_test(md, vl_test1, vl_test2),
3532 "This brick do not support the assembly on both an affine " 3533 "dependent variable and its original variable. " 3534 "Split the brick.");
3536 if (vl_test1.size()) {
3537 pbrick pbr = std::make_shared<gen_linear_assembly_brick>
3538 (expr, mim, is_sym, is_coercive, brickname, vl_test1, vl_test2);
3540 for (
size_type i = 0; i < vl_test1.size(); ++i)
3541 tl.push_back(model::term_description(vl_test1[i], vl_test2[i],
false));
3543 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
3555 struct gen_nonlinear_assembly_brick :
public virtual_brick {
3560 virtual void real_post_assembly_in_serial(
const model &md,
size_type ,
3561 const model::varnamelist &,
3562 const model::varnamelist &,
3563 const model::mimlist &mims,
3564 model::real_matlist &,
3565 model::real_veclist &,
3566 model::real_veclist &,
3568 build_version)
const {
3569 GMM_ASSERT1(mims.size() == 1,
3570 "Generic linear assembly brick needs one and only one " 3572 md.add_generic_expression(expr, *(mims[0]), region);
3575 virtual std::string declare_volume_assembly_string
3577 const model::varnamelist &)
const {
3582 gen_nonlinear_assembly_brick(
const std::string &expr_,
const mesh_im &mim,
3584 bool is_coer, std::string brickname =
"") {
3585 if (brickname.size() == 0) brickname =
"Generic linear assembly brick";
3587 is_lower_dim = mim.is_lower_dimensional();
3588 set_flags(brickname,
false ,
3597 bool is_sym,
bool is_coercive, std::string brickname) {
3599 ga_workspace workspace(md);
3600 size_type order = workspace.add_expression(expr, mim, region);
3601 GMM_ASSERT1(order < 2,
"Order two test functions (Test2) are not allowed" 3602 " in assembly string for nonlinear terms");
3603 model::varnamelist vl, vl_test1, vl_test2, ddl, dl;
3604 workspace.used_variables(vl, vl_test1, vl_test2, ddl, order);
3605 for (
size_type i = 0; i < ddl.size(); ++i)
3607 else vl.push_back(ddl[i]);
3608 if (order == 0) { is_coercive = is_sym =
true; }
3609 pbrick pbr = std::make_shared<gen_nonlinear_assembly_brick>
3610 (expr, mim, is_sym, is_coercive, brickname);
3614 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
3627 const model::varnamelist &vl,
3628 const model::varnamelist &dl,
3629 const model::mimlist &mims,
3630 model::real_matlist &matl,
3631 model::real_veclist &,
3632 model::real_veclist &,
3634 build_version)
const {
3635 GMM_ASSERT1(matl.size() == 1,
3636 "Generic elliptic brick has one and only one term");
3637 GMM_ASSERT1(mims.size() == 1,
3638 "Generic elliptic brick need one and only one mesh_im");
3639 GMM_ASSERT1(vl.size() == 1 && dl.size() <= 1,
3640 "Wrong number of variables for generic elliptic brick");
3643 const mesh &m = mf_u.linked_mesh();
3644 size_type N = m.dim(), Q = mf_u.get_qdim(), s = 1;
3645 const mesh_im &mim = *mims[0];
3646 const model_real_plain_vector *A = 0;
3649 m.intersect_with_mpi_region(rg);
3650 if (dl.size() > 0) {
3653 s = gmm::vect_size(*A);
3657 gmm::clear(matl[0]);
3658 GMM_TRACE2(
"Generic elliptic term assembly");
3663 (matl[0], mim, mf_u, *mf_a, *A, rg);
3666 (matl[0], mim, mf_u, *mf_a, *A, rg);
3671 (matl[0], mim, mf_u, rg);
3674 (matl[0], mim, mf_u, rg);
3675 if (A) gmm::scale(matl[0], (*A)[0]);
3677 }
else if (s == N*N) {
3681 (matl[0], mim, mf_u, *mf_a, *A, rg);
3684 (matl[0], mim, mf_u, *mf_a, *A, rg);
3688 (matl[0], mim, mf_u, *A, rg);
3691 (matl[0], mim, mf_u, *A, rg);
3693 }
else if (s == N*N*Q*Q) {
3696 (matl[0], mim, mf_u, *mf_a, *A, rg);
3699 (matl[0], mim, mf_u, *A, rg);
3701 GMM_ASSERT1(
false,
"Bad format generic elliptic brick coefficient");
3705 virtual void real_post_assembly_in_serial(
const model &md,
size_type,
3706 const model::varnamelist &,
3707 const model::varnamelist &dl,
3708 const model::mimlist &,
3709 model::real_matlist &,
3710 model::real_veclist &,
3711 model::real_veclist &,
3713 build_version)
const 3715 const model_real_plain_vector *A = 0;
3724 virtual void complex_post_assembly_in_serial(
const model &md,
size_type,
3725 const model::varnamelist &,
3726 const model::varnamelist &dl,
3727 const model::mimlist &,
3728 model::complex_matlist &,
3729 model::complex_veclist &,
3730 model::complex_veclist &,
3732 build_version)
const 3734 const model_real_plain_vector *A = 0;
3743 virtual scalar_type asm_complex_tangent_terms(
const model &md,
size_type,
3744 const model::varnamelist &vl,
3745 const model::varnamelist &,
3746 const model::mimlist &,
3747 model::complex_matlist &matl,
3748 model::complex_veclist &,
3749 model::complex_veclist &,
3752 return gmm::abs(gmm::vect_hp(matl[0], U, U)) / scalar_type(2);
3756 virtual void asm_complex_tangent_terms(
const model &md,
size_type,
3757 const model::varnamelist &vl,
3758 const model::varnamelist &dl,
3759 const model::mimlist &mims,
3760 model::complex_matlist &matl,
3761 model::complex_veclist &,
3762 model::complex_veclist &,
3764 build_version)
const {
3765 GMM_ASSERT1(matl.size() == 1,
3766 "Generic elliptic brick has one and only one term");
3767 GMM_ASSERT1(mims.size() == 1,
3768 "Generic elliptic brick need one and only one mesh_im");
3769 GMM_ASSERT1(vl.size() == 1 && dl.size() <= 1,
3770 "Wrong number of variables for generic elliptic brick");
3773 const mesh &m = mf_u.linked_mesh();
3774 size_type N = m.dim(), Q = mf_u.get_qdim(), s = 1;
3775 const mesh_im &mim = *mims[0];
3776 const model_real_plain_vector *A = 0;
3779 m.intersect_with_mpi_region(rg);
3782 if (dl.size() > 0) {
3785 s = gmm::vect_size(*A);
3789 gmm::clear(matl[0]);
3790 GMM_TRACE2(
"Generic elliptic term assembly");
3795 (matl[0], mim, mf_u, *mf_a, *A, rg);
3798 (matl[0], mim, mf_u, *mf_a, *A, rg);
3803 (gmm::real_part(matl[0]), mim, mf_u, rg);
3806 (gmm::real_part(matl[0]), mim, mf_u, rg);
3807 if (A) gmm::scale(matl[0], (*A)[0]);
3809 }
else if (s == N*N) {
3813 (matl[0], mim, mf_u, *mf_a, *A, rg);
3816 (matl[0], mim, mf_u, *mf_a, *A, rg);
3820 (matl[0], mim, mf_u, *A, rg);
3823 (matl[0], mim, mf_u, *A, rg);
3825 }
else if (s == N*N*Q*Q) {
3828 (matl[0], mim, mf_u, *mf_a, *A, rg);
3831 (matl[0], mim, mf_u, *A, rg);
3834 "Bad format generic elliptic brick coefficient");
3837 generic_elliptic_brick() {
3838 set_flags(
"Generic elliptic",
true ,
3846 const std::string &varname,
3849 pbrick pbr = std::make_shared<generic_elliptic_brick>();
3851 tl.push_back(model::term_description(varname, varname,
true));
3852 return md.
add_brick(pbr, model::varnamelist(1, varname),
3853 model::varnamelist(), tl, model::mimlist(1, &mim),
3856 std::string test_varname
3857 =
"Test_" + sup_previous_and_dot_to_varname(varname);
3862 expr =
"Grad_"+varname+
".Grad_"+test_varname;
3864 expr =
"Grad_"+varname+
":Grad_"+test_varname;
3866 "Laplacian",
false);
3871 const std::string &varname,
3872 const std::string &dataname,
3875 pbrick pbr = std::make_shared<generic_elliptic_brick>();
3877 tl.push_back(model::term_description(varname, varname,
true));
3878 return md.
add_brick(pbr, model::varnamelist(1, varname),
3879 model::varnamelist(1, dataname), tl,
3880 model::mimlist(1, &mim), region);
3882 std::string test_varname
3883 =
"Test_" + sup_previous_and_dot_to_varname(varname);
3896 if (qdim_data != 1) {
3897 GMM_ASSERT1(qdim_data == gmm::sqr(dim),
3898 "Wrong data size for generic elliptic brick");
3899 expr =
"((Reshape("+dataname+
",meshdim,meshdim))*Grad_"+varname+
").Grad_" 3902 expr =
"(("+dataname+
")*Grad_"+varname+
").Grad_"+test_varname;
3905 if (qdim_data != 1) {
3906 if (qdim_data == gmm::sqr(dim))
3907 expr =
"((Reshape("+dataname+
",meshdim,meshdim))*Grad_"+varname+
"):Grad_" 3909 else if (qdim_data == gmm::sqr(gmm::sqr(dim)))
3910 expr =
"((Reshape("+dataname+
",meshdim,meshdim,meshdim,meshdim))*Grad_" 3911 +varname+
"):Grad_"+test_varname;
3912 else GMM_ASSERT1(
false,
"Wrong data size for generic elliptic brick");
3914 expr =
"(("+dataname+
")*Grad_"+varname+
"):Grad_"+test_varname;
3918 (md, mim, expr, region,
true,
true,
"Generic elliptic",
true);
3921 "Generic elliptic (nonlinear)");
3936 const model::varnamelist &vl,
3937 const model::varnamelist &dl,
3938 const model::mimlist &mims,
3939 model::real_matlist &,
3940 model::real_veclist &vecl,
3941 model::real_veclist &,
3943 build_version)
const override {
3944 GMM_ASSERT1(vecl.size() == 1,
3945 "Source term brick has one and only one term");
3946 GMM_ASSERT1(mims.size() == 1,
3947 "Source term brick need one and only one mesh_im");
3948 GMM_ASSERT1(vl.size() == 1 && dl.size() > 0 && dl.size() <= 2,
3949 "Wrong number of variables for source term brick");
3952 const mesh_im &mim = *mims[0];
3961 GMM_ASSERT1(mf_u.get_qdim() == s,
3962 dl[0] <<
": bad format of source term data. " 3963 "Detected dimension is " << s <<
" should be " 3966 GMM_TRACE2(
"Source term assembly");
3972 if (dl.size() > 1) gmm::add(md.
real_variable(dl[1]), vecl[0]);
3976 const model::varnamelist &,
3977 const model::varnamelist &,
3978 const model::mimlist &,
3979 model::real_matlist &,
3980 model::real_veclist &vecl,
3981 model::real_veclist &,
3983 build_version)
const override 3985 md.add_external_load(ib, gmm::vect_norm1(vecl[0]));
3990 const model::varnamelist &vl,
3991 const model::varnamelist &dl,
3992 const model::mimlist &mims,
3993 model::complex_matlist &,
3994 model::complex_veclist &vecl,
3995 model::complex_veclist &,
3997 build_version)
const override {
3998 GMM_ASSERT1(vecl.size() == 1,
3999 "Source term brick has one and only one term");
4000 GMM_ASSERT1(mims.size() == 1,
4001 "Source term brick need one and only one mesh_im");
4002 GMM_ASSERT1(vl.size() == 1 && dl.size() > 0 && dl.size() <= 2,
4003 "Wrong number of variables for source term brick");
4006 const mesh_im &mim = *mims[0];
4015 GMM_ASSERT1(mf_u.get_qdim() == s,
"Bad format of source term data");
4017 GMM_TRACE2(
"Source term assembly");
4026 void complex_post_assembly_in_serial(
const model &md,
4028 const model::varnamelist &,
4029 const model::varnamelist &,
4030 const model::mimlist &,
4031 model::complex_matlist &,
4032 model::complex_veclist &vecl,
4033 model::complex_veclist &,
4034 size_type, build_version)
const override 4036 md.add_external_load(ib, gmm::vect_norm1(vecl[0]));
4041 source_term_brick() {
4042 set_flags(
"Source term",
true ,
4052 const std::string &varname,
4053 const std::string &dataexpr,
4055 const std::string &directdataname) {
4057 pbrick pbr = std::make_shared<source_term_brick>();
4059 tl.push_back(model::term_description(varname));
4060 model::varnamelist vdata(1, dataexpr);
4061 if (directdataname.size()) vdata.push_back(directdataname);
4062 return md.
add_brick(pbr, model::varnamelist(1, varname),
4063 vdata, tl, model::mimlist(1, &mim), region);
4065 std::string test_varname
4066 =
"Test_" + sup_previous_and_dot_to_varname(varname);
4071 expr =
"("+dataexpr+
")*"+test_varname;
4073 expr =
"("+dataexpr+
")."+test_varname;
4074 size_type ib = add_source_term_generic_assembly_brick
4075 (md, mim, expr, region,
"Source term", varname, directdataname,
true);
4078 "Source term (nonlinear)");
4079 if (directdataname.size())
4080 add_source_term_generic_assembly_brick
4081 (md, mim,
"", region,
"Source term", varname, directdataname);
4096 const model::varnamelist &vl,
4097 const model::varnamelist &dl,
4098 const model::mimlist &mims,
4099 model::real_matlist &,
4100 model::real_veclist &vecl,
4101 model::real_veclist &,
4103 build_version)
const override {
4104 GMM_ASSERT1(vecl.size() == 1,
4105 "Source term brick has one and only one term");
4106 GMM_ASSERT1(mims.size() == 1,
4107 "Source term brick need one and only one mesh_im");
4108 GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
4109 "Wrong number of variables for source term brick");
4112 const mesh_im &mim = *mims[0];
4118 size_type s = gmm::vect_size(A), N = mf_u.linked_mesh().dim();
4121 GMM_ASSERT1(mf_u.get_qdim()*N == s,
4122 dl[0] <<
": bad format of normal source term data. " 4123 "Detected dimension is " << s <<
" should be " 4126 GMM_TRACE2(
"source term assembly");
4134 const model::varnamelist &,
4135 const model::varnamelist &,
4136 const model::mimlist &,
4137 model::real_matlist &,
4138 model::real_veclist &vecl,
4139 model::real_veclist &,
4141 build_version)
const override {
4142 md.add_external_load(ib, gmm::vect_norm1(vecl[0]));
4146 virtual void asm_complex_tangent_terms(
const model &md,
size_type ,
4147 const model::varnamelist &vl,
4148 const model::varnamelist &dl,
4149 const model::mimlist &mims,
4150 model::complex_matlist &,
4151 model::complex_veclist &vecl,
4152 model::complex_veclist &,
4154 build_version)
const {
4155 GMM_ASSERT1(vecl.size() == 1,
4156 "Source term brick has one and only one term");
4157 GMM_ASSERT1(mims.size() == 1,
4158 "Source term brick need one and only one mesh_im");
4159 GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
4160 "Wrong number of variables for source term brick");
4163 const mesh_im &mim = *mims[0];
4169 size_type s = gmm::vect_size(A), N = mf_u.linked_mesh().dim();
4172 GMM_ASSERT1(s == mf_u.get_qdim()*N,
"Bad format of source term data");
4174 GMM_TRACE2(
"source term assembly");
4181 void complex_post_assembly_in_serial(
const model &md,
size_type ib,
4182 const model::varnamelist &,
4183 const model::varnamelist &,
4184 const model::mimlist &,
4185 model::complex_matlist &,
4186 model::complex_veclist &vecl,
4187 model::complex_veclist &,
4189 build_version)
const override {
4190 md.add_external_load(ib, gmm::vect_norm1(vecl[0]));
4193 normal_source_term_brick() {
4194 set_flags(
"Normal source term",
true ,
4204 const std::string &varname,
4205 const std::string &dataexpr,
4208 pbrick pbr = std::make_shared<normal_source_term_brick>();
4210 tl.push_back(model::term_description(varname));
4211 model::varnamelist vdata(1, dataexpr);
4212 return md.
add_brick(pbr, model::varnamelist(1, varname),
4213 vdata, tl, model::mimlist(1, &mim), region);
4215 std::string test_varname
4216 =
"Test_" + sup_previous_and_dot_to_varname(varname);
4221 expr =
"(("+dataexpr+
").Normal)*"+test_varname;
4223 expr =
"(Reshape("+dataexpr+
",qdim("+varname
4224 +
"),meshdim)*Normal)."+test_varname;
4225 return add_source_term_generic_assembly_brick
4226 (md, mim, expr, region,
"Source term");
4242 bool normal_component;
4249 virtual void asm_real_tangent_terms(
const model &md,
size_type ib,
4250 const model::varnamelist &vl,
4251 const model::varnamelist &dl,
4252 const model::mimlist &mims,
4253 model::real_matlist &matl,
4254 model::real_veclist &vecl,
4255 model::real_veclist &,
4257 build_version version)
const {
4258 GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
4259 "Dirichlet condition brick has one and only one term");
4260 GMM_ASSERT1(mims.size() == 1,
4261 "Dirichlet condition brick need one and only one mesh_im");
4262 GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2 && dl.size() <= 3,
4263 "Wrong number of variables for Dirichlet condition brick");
4265 model_real_sparse_matrix& rB = rB_th;
4266 model_real_plain_vector& rV = rV_th;
4268 bool penalized = (vl.size() == 1);
4270 const mesh_fem &mf_mult = penalized ? (mf_mult_ ? *mf_mult_ : mf_u)
4272 const mesh_im &mim = *mims[0];
4273 const model_real_plain_vector *A = 0, *COEFF = 0, *H = 0;
4274 const mesh_fem *mf_data = 0, *mf_H = 0;
4275 bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
4276 || (penalized && md.is_var_newer_than_brick(dl[0], ib));
4280 GMM_ASSERT1(gmm::vect_size(*COEFF) == 1,
4281 "Data for coefficient should be a scalar");
4284 size_type s = 0, ind = (penalized ? 1 : 0);
4285 if (dl.size() > ind) {
4288 s = gmm::vect_size(*A);
4291 GMM_ASSERT1(s == ss, dl[ind] <<
": bad format of " 4292 "Dirichlet data. Detected dimension is " << s
4293 <<
" should be " << ss);
4296 if (dl.size() > ind + 1) {
4297 GMM_ASSERT1(H_version,
4298 "Wrong number of data for Dirichlet condition brick");
4301 s = gmm::vect_size(*A);
4303 s = s * mf_H->get_qdim() / mf_H->nb_dof();
4304 GMM_ASSERT1(mf_H->get_qdim() == 1,
"Implemented only for mf_H " 4305 "a scalar finite element method");
4307 GMM_ASSERT1(s = gmm::sqr(mf_u.
get_qdim()),
4308 dl[ind+1] <<
": bad format of Dirichlet data. " 4309 "Detected dimension is " << s <<
" should be " 4316 if (recompute_matrix) {
4317 model_real_sparse_matrix *B = &(matl[0]);
4318 if (penalized && (&mf_mult != &mf_u)) {
4323 gmm::clear(matl[0]);
4325 GMM_TRACE2(
"Mass term assembly for Dirichlet condition");
4326 if (H_version || normal_component) {
4327 ga_workspace workspace;
4328 gmm::sub_interval Imult(0, mf_mult.
nb_dof()), Iu(0, mf_u.
nb_dof());
4329 base_vector u(mf_u.
nb_dof());
4330 base_vector mult(mf_mult.
nb_dof());
4331 workspace.add_fem_variable(
"u", mf_u, Iu, u);
4332 workspace.add_fem_variable(
"mult", mf_mult, Imult, mult);
4333 auto expression = std::string{};
4335 if (mf_H) workspace.add_fem_constant(
"A", *mf_H, *H);
4336 else workspace.add_fixed_size_constant(
"A", *H);
4337 expression = (mf_u.
get_qdim() == 1) ?
4338 "Test_mult . (A . Test2_u)" 4340 "Test_mult. (Reshape(A, qdim(u), qdim(u)) . Test2_u)";
4341 }
else if (normal_component) {
4342 expression =
"Test_mult . (Test2_u . Normal)";
4344 workspace.add_expression(expression, mim, rg);
4345 workspace.set_assembled_matrix(*B);
4346 workspace.assembly(2);
4351 if (penalized && (&mf_mult != &mf_u)) {
4352 GMM_ASSERT1(MPI_IS_MASTER(),
"Sorry, the penalized option " 4353 "filtered by a multiplier space is not parallelized");
4354 gmm::mult(gmm::transposed(rB), rB, matl[0]);
4355 gmm::scale(matl[0], gmm::abs((*COEFF)[0]));
4356 }
else if (penalized) {
4357 gmm::scale(matl[0], gmm::abs((*COEFF)[0]));
4361 if (dl.size() > ind) {
4362 GMM_TRACE2(
"Source term assembly for Dirichlet condition");
4364 if (penalized && (&mf_mult != &mf_u)) {
4365 gmm::resize(rV, mf_mult.
nb_dof());
4378 if (penalized && (&mf_mult != &mf_u)) {
4379 gmm::mult(gmm::transposed(rB), rV, vecl[0]);
4380 gmm::scale(vecl[0], gmm::abs((*COEFF)[0]));
4381 rV = model_real_plain_vector();
4382 }
else if (penalized)
4383 gmm::scale(vecl[0], gmm::abs((*COEFF)[0]));
4389 const model::varnamelist &,
4390 const model::varnamelist &,
4391 const model::mimlist &,
4392 model::real_matlist &,
4393 model::real_veclist &vecl,
4394 model::real_veclist &,
4396 build_version)
const override {
4397 md.add_external_load(ib, gmm::vect_norm1(vecl[0]));
4400 virtual void asm_complex_tangent_terms(
const model &md,
size_type ib,
4401 const model::varnamelist &vl,
4402 const model::varnamelist &dl,
4403 const model::mimlist &mims,
4404 model::complex_matlist &matl,
4405 model::complex_veclist &vecl,
4406 model::complex_veclist &,
4408 build_version version)
const {
4409 GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
4410 "Dirichlet condition brick has one and only one term");
4411 GMM_ASSERT1(mims.size() == 1,
4412 "Dirichlet condition brick need one and only one mesh_im");
4413 GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2 && dl.size() <= 3,
4414 "Wrong number of variables for Dirichlet condition brick");
4416 model_complex_sparse_matrix& cB = cB_th;
4417 model_complex_plain_vector& cV = cV_th;
4419 bool penalized = (vl.size() == 1);
4421 const mesh_fem &mf_mult = penalized ? (mf_mult_ ? *mf_mult_ : mf_u)
4423 const mesh_im &mim = *mims[0];
4424 const model_complex_plain_vector *A = 0, *COEFF = 0, *H = 0;
4425 const mesh_fem *mf_data = 0, *mf_H = 0;
4426 bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
4427 || (penalized && md.is_var_newer_than_brick(dl[0], ib));
4431 GMM_ASSERT1(gmm::vect_size(*COEFF) == 1,
4432 "Data for coefficient should be a scalar");
4435 size_type s = 0, ind = (penalized ? 1 : 0);
4436 if (dl.size() > ind) {
4439 s = gmm::vect_size(*A);
4443 dl[ind] <<
": bad format of Dirichlet data. " 4444 "Detected dimension is " << ss <<
" should be " 4448 if (dl.size() > ind + 1) {
4449 GMM_ASSERT1(H_version,
4450 "Wrong number of data for Dirichlet condition brick");
4453 s = gmm::vect_size(*A);
4455 s = s * mf_H->get_qdim() / mf_H->nb_dof();
4456 GMM_ASSERT1(mf_H->get_qdim() == 1,
"Implemented only for mf_H " 4457 "a scalar finite element method");
4459 GMM_ASSERT1(s = gmm::sqr(mf_u.
get_qdim()),
4460 dl[ind+1] <<
": bad format of Dirichlet data. " 4461 "Detected dimension is " << s <<
" should be " 4468 if (recompute_matrix) {
4469 model_complex_sparse_matrix *B = &(matl[0]);
4470 if (penalized && (&mf_mult != &mf_u)) {
4475 gmm::clear(matl[0]);
4477 GMM_TRACE2(
"Mass term assembly for Dirichlet condition");
4480 asm_real_or_complex_1_param_mat(*B, mim, mf_mult, mf_H, *H, rg,
4481 "(A*Test_u).Test2_u");
4483 asm_real_or_complex_1_param_mat(*B, mim, mf_mult, mf_H, *H, rg,
4484 "(Reshape(A,qdim(u),qdim(u))*Test2_u).Test_u");
4500 else if (normal_component) {
4501 ga_workspace workspace;
4502 gmm::sub_interval Imult(0, mf_mult.
nb_dof()), Iu(0, mf_u.
nb_dof());
4504 workspace.add_fem_variable(
"mult", mf_mult, Imult, mult);
4505 workspace.add_fem_variable(
"u", mf_u, Iu, u);
4506 workspace.add_expression(
"Test_mult.(Test2_u.Normal)", mim, rg);
4507 model_real_sparse_matrix BB(mf_mult.
nb_dof(), mf_u.
nb_dof());
4508 workspace.set_assembled_matrix(BB);
4509 workspace.assembly(2);
4525 if (penalized && (&mf_mult != &mf_u)) {
4526 gmm::mult(gmm::transposed(cB), cB, matl[0]);
4527 gmm::scale(matl[0], gmm::abs((*COEFF)[0]));
4528 }
else if (penalized) {
4529 gmm::scale(matl[0], gmm::abs((*COEFF)[0]));
4533 if (dl.size() > ind) {
4534 GMM_TRACE2(
"Source term assembly for Dirichlet condition");
4536 if (penalized && (&mf_mult != &mf_u)) {
4537 gmm::resize(cV, mf_mult.
nb_dof());
4550 if (penalized && (&mf_mult != &mf_u)) {
4551 gmm::mult(gmm::transposed(cB), cV, vecl[0]);
4552 gmm::scale(vecl[0], gmm::abs((*COEFF)[0]));
4553 cV = model_complex_plain_vector();
4554 }
else if (penalized)
4555 gmm::scale(vecl[0], gmm::abs((*COEFF)[0]));
4559 void complex_post_assembly_in_serial(
const model &md,
size_type ib,
4560 const model::varnamelist &,
4561 const model::varnamelist &,
4562 const model::mimlist &,
4563 model::complex_matlist &,
4564 model::complex_veclist &vecl,
4565 model::complex_veclist &,
4567 build_version)
const override {
4568 md.add_external_load(ib, gmm::vect_norm1(vecl[0]));
4572 virtual std::string declare_volume_assembly_string
4574 const model::varnamelist &)
const {
4575 return std::string();
4578 Dirichlet_condition_brick(
bool penalized,
bool H_version_,
4579 bool normal_component_,
4581 mf_mult_ = mf_mult__;
4582 H_version = H_version_;
4583 normal_component = normal_component_;
4584 GMM_ASSERT1(!(H_version && normal_component),
"Bad Dirichlet version");
4585 set_flags(penalized ?
"Dirichlet with penalization brick" 4586 :
"Dirichlet with multipliers brick",
4596 const std::string &multname,
size_type region,
4597 const std::string &dataname) {
4598 pbrick pbr = std::make_shared<Dirichlet_condition_brick>(
false,
false,
false);
4600 tl.push_back(model::term_description(multname, varname,
true));
4601 model::varnamelist vl(1, varname);
4602 vl.push_back(multname);
4603 model::varnamelist dl;
4604 if (dataname.size()) dl.push_back(dataname);
4605 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
4611 const std::string &dataname) {
4612 std::string multname = md.
new_name(
"mult_on_" + varname);
4615 (md, mim, varname, multname, region, dataname);
4621 const std::string &dataname) {
4626 (md, mim, varname, mf_mult, region, dataname);
4635 scalar_type penalisation_coeff,
size_type region,
4636 const std::string &dataname,
const mesh_fem *mf_mult) {
4637 std::string coeffname = md.
new_name(
"penalization_on_" + varname);
4643 pbrick pbr = std::make_shared<Dirichlet_condition_brick>
4644 (
true,
false,
false, mf_mult);
4646 tl.push_back(model::term_description(varname, varname,
true));
4647 model::varnamelist vl(1, varname);
4648 model::varnamelist dl(1, coeffname);
4649 if (dataname.size()) dl.push_back(dataname);
4650 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
4655 const std::string &multname,
size_type region,
4656 const std::string &dataname) {
4657 pbrick pbr = std::make_shared<Dirichlet_condition_brick>(
false,
false,
true);
4659 tl.push_back(model::term_description(multname, varname,
true));
4660 model::varnamelist vl(1, varname);
4661 vl.push_back(multname);
4662 model::varnamelist dl;
4663 if (dataname.size()) dl.push_back(dataname);
4664 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
4670 const std::string &dataname) {
4671 std::string multname = md.
new_name(
"mult_on_" + varname);
4674 (md, mim, varname, multname, region, dataname);
4680 const std::string &dataname) {
4684 (md, mim, varname, mf_mult, region, dataname);
4689 scalar_type penalisation_coeff,
size_type region,
4690 const std::string &dataname,
const mesh_fem *mf_mult) {
4691 std::string coeffname = md.
new_name(
"penalization_on_" + varname);
4697 pbrick pbr = std::make_shared<Dirichlet_condition_brick>
4698 (
true,
false,
true, mf_mult);
4700 tl.push_back(model::term_description(varname, varname,
true));
4701 model::varnamelist vl(1, varname);
4702 model::varnamelist dl(1, coeffname);
4703 if (dataname.size()) dl.push_back(dataname);
4704 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
4710 const std::string &multname,
size_type region,
4711 const std::string &dataname,
const std::string &Hname) {
4712 pbrick pbr = std::make_shared<Dirichlet_condition_brick>(
false,
true,
false);
4714 tl.push_back(model::term_description(multname, varname,
true));
4715 model::varnamelist vl(1, varname);
4716 vl.push_back(multname);
4717 model::varnamelist dl;
4718 dl.push_back(dataname);
4719 dl.push_back(Hname);
4720 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
4726 const std::string &dataname,
const std::string &Hname) {
4727 std::string multname = md.
new_name(
"mult_on_" + varname);
4730 (md, mim, varname, multname, region, dataname, Hname);
4736 const std::string &dataname,
const std::string &Hname) {
4741 (md, mim, varname, mf_mult, region, dataname, Hname);
4746 scalar_type penalisation_coeff,
size_type region,
4747 const std::string &dataname,
const std::string &Hname,
4749 std::string coeffname = md.
new_name(
"penalization_on_" + varname);
4755 pbrick pbr = std::make_shared<Dirichlet_condition_brick>
4756 (
true,
true,
false, mf_mult);
4758 tl.push_back(model::term_description(varname, varname,
true));
4759 model::varnamelist vl(1, varname);
4760 model::varnamelist dl(1, coeffname);
4761 dl.push_back(dataname);
4762 dl.push_back(Hname);
4763 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
4767 scalar_type penalisation_coeff) {
4771 GMM_ASSERT1(gmm::vect_size(d)==1,
4772 "Wrong coefficient size, may be not a Dirichlet brick " 4773 "with penalization");
4774 d[0] = penalisation_coeff;
4778 GMM_ASSERT1(gmm::vect_size(d)==1,
4779 "Wrong coefficient size, may be not a Dirichlet brick " 4780 "with penalization");
4781 d[0] = penalisation_coeff;
4791 struct simplification_Dirichlet_condition_brick :
public virtual_brick {
4794 const model::varnamelist &vl,
4795 const model::varnamelist &dl,
4796 const model::mimlist &mims,
4797 model::real_matlist &matl,
4798 model::real_veclist &vecl,
4799 model::real_veclist &,
4801 build_version )
const {
4802 if (MPI_IS_MASTER()) {
4804 GMM_ASSERT1(vecl.size() == 0 && matl.size() == 0,
4805 "Dirichlet condition brick by simplification has no term");
4806 GMM_ASSERT1(mims.size() == 0,
4807 "Dirichlet condition brick by simplification need no " 4809 GMM_ASSERT1(vl.size() == 1 && dl.size() <= 1,
4810 "Wrong number of variables for Dirichlet condition brick " 4811 "by simplification");
4814 const model_real_plain_vector *A = 0;
4818 if (dl.size() == 1) {
4823 GMM_ASSERT1(mf_data == &mf_u,
"Sorry, for this brick, the data has" 4824 " to be defined on the same f.e.m. as the unknown");
4826 s = gmm::vect_size(*A);
4827 GMM_ASSERT1(mf_u.get_qdim() == s,
": bad format of " 4828 "Dirichlet data. Detected dimension is " << s
4829 <<
" should be " <<
size_type(mf_u.get_qdim()));
4836 if (mf_u.get_qdim() > 1 || (!mf_data && A)) {
4837 for (
mr_visitor i(rg, mf_u.linked_mesh()); !i.finished(); ++i) {
4838 pfem pf = mf_u.fem_of_element(i.cv());
4840 GMM_ASSERT1(pf->target_dim() == 1,
4841 "Intrinsically vectorial fems are not allowed");
4842 GMM_ASSERT1(mf_data || pf->is_lagrange(),
"Constant Dirichlet " 4843 "data allowed for lagrange fems only");
4848 dal::bit_vector dofs = mf_u.dof_on_region(rg);
4850 if (A && !mf_data) {
4851 GMM_ASSERT1(dofs.card() % s == 0,
"Problem with dof vectorization");
4854 for (dal::bv_visitor i(dofs); !i.finished(); ++i) {
4856 if (A) val = (mf_data ? (*A)[i] : (*A)[i%s]);
4857 md.add_real_dof_constraint(vl[0], i, val);
4862 virtual void asm_complex_tangent_terms(
const model &md,
size_type ,
4863 const model::varnamelist &vl,
4864 const model::varnamelist &dl,
4865 const model::mimlist &mims,
4866 model::complex_matlist &matl,
4867 model::complex_veclist &vecl,
4868 model::complex_veclist &,
4870 build_version )
const {
4871 if (MPI_IS_MASTER()) {
4872 GMM_ASSERT1(vecl.size() == 0 && matl.size() == 0,
4873 "Dirichlet condition brick by simplification has no term");
4874 GMM_ASSERT1(mims.size() == 0,
4875 "Dirichlet condition brick by simplification need no " 4877 GMM_ASSERT1(vl.size() == 1 && dl.size() <= 1,
4878 "Wrong number of variables for Dirichlet condition brick " 4879 "by simplification");
4882 const model_complex_plain_vector *A = 0;
4886 if (dl.size() == 1) {
4891 GMM_ASSERT1(mf_data == &mf_u,
"Sorry, for this brick, the data has" 4892 " to be define on the same f.e.m. than the unknown");
4894 s = gmm::vect_size(*A);
4895 GMM_ASSERT1(mf_u.get_qdim() == s,
": bad format of " 4896 "Dirichlet data. Detected dimension is " << s
4897 <<
" should be " <<
size_type(mf_u.get_qdim()));
4904 if (mf_u.get_qdim() > 1 || (!mf_data && A)) {
4905 for (
mr_visitor i(rg, mf_u.linked_mesh()); !i.finished(); ++i) {
4906 pfem pf = mf_u.fem_of_element(i.cv());
4908 GMM_ASSERT1(pf->target_dim() == 1,
4909 "Intrinsically vectorial fems are not allowed");
4910 GMM_ASSERT1(mf_data || pf->is_lagrange(),
"Constant Dirichlet " 4911 "data allowed for lagrange fems only");
4916 dal::bit_vector dofs = mf_u.dof_on_region(rg);
4918 if (A && !mf_data) {
4919 GMM_ASSERT1(dofs.card() % s == 0,
"Problem with dof vectorization");
4922 for (dal::bv_visitor i(dofs); !i.finished(); ++i) {
4923 complex_type val(0);
4924 if (A) val = (mf_data ? (*A)[i] : (*A)[i%s]);
4925 md.add_complex_dof_constraint(vl[0], i, val);
4931 virtual std::string declare_volume_assembly_string
4933 const model::varnamelist &)
const {
4934 return std::string();
4937 simplification_Dirichlet_condition_brick() {
4938 set_flags(
"Dirichlet with simplification brick",
4948 size_type region,
const std::string &dataname) {
4949 pbrick pbr = std::make_shared<simplification_Dirichlet_condition_brick>();
4951 model::varnamelist vl(1, varname);
4952 model::varnamelist dl;
4953 if (dataname.size()) dl.push_back(dataname);
4954 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(), region);
4965 const std::string &Neumannterm,
4966 const std::string &datagamma0,
size_type region, scalar_type theta_,
4967 const std::string &datag) {
4969 std::string theta = std::to_string(theta_);
4970 ga_workspace workspace(md,
true);
4971 size_type order = workspace.add_expression(Neumannterm, mim, region, 1);
4972 GMM_ASSERT1(order == 0,
"Wrong expression of the Neumann term");
4973 model::varnamelist vl, vl_test1, vl_test2, dl;
4974 bool is_lin = workspace.used_variables(vl, vl_test1, vl_test2, dl, 1);
4976 std::string condition =
"("+varname + (datag.size() ?
"-("+datag+
"))":
")");
4977 std::string gamma =
"(("+datagamma0+
")*element_size)";
4978 std::string r =
"(1/"+gamma+
")";
4979 std::string expr =
"("+r+
"*"+condition+
"-("+Neumannterm+
")).Test_"+varname;
4980 if (theta_ != scalar_type(0)) {
4981 std::string derivative_Neumann = workspace.extract_order1_term(varname);
4982 if (derivative_Neumann.size())
4983 expr+=
"-"+theta+
"*"+condition+
".("+derivative_Neumann+
")";
4991 "Dirichlet condition with Nitsche's method");
4994 "Dirichlet condition with Nitsche's method");
5000 const std::string &Neumannterm,
5001 const std::string &datagamma0,
size_type region, scalar_type theta_,
5002 const std::string &datag) {
5003 std::string theta = std::to_string(theta_);
5004 ga_workspace workspace(md,
true);
5005 size_type order = workspace.add_expression(Neumannterm, mim, region, 1);
5006 GMM_ASSERT1(order == 0,
"Wrong expression of the Neumann term");
5007 model::varnamelist vl, vl_test1, vl_test2, dl;
5008 bool is_lin = workspace.used_variables(vl, vl_test1, vl_test2, dl, 1);
5010 std::string condition =
"("+varname+
".Normal" 5011 + (datag.size() ?
"-("+datag+
"))":
")");
5012 std::string gamma =
"(("+datagamma0+
")*element_size)";
5013 std::string r =
"(1/"+gamma+
")";
5014 std::string expr =
"("+r+
"*"+condition+
"-Normal.("+Neumannterm
5015 +
"))*(Normal.Test_"+varname+
")";
5016 if (theta_ != scalar_type(0)) {
5017 std::string derivative_Neumann = workspace.extract_order1_term(varname);
5018 if (derivative_Neumann.size())
5019 expr+=
"-"+theta+
"*"+condition+
"*Normal.(" 5020 +derivative_Neumann+
")";
5024 "Dirichlet condition with Nitsche's method");
5027 "Dirichlet condition with Nitsche's method");
5033 const std::string &Neumannterm,
5034 const std::string &datagamma0,
size_type region, scalar_type theta_,
5035 const std::string &datag,
const std::string &dataH) {
5036 std::string theta = std::to_string(theta_);
5037 ga_workspace workspace(md,
true);
5038 size_type order = workspace.add_expression(Neumannterm, mim, region, 1);
5039 GMM_ASSERT1(order == 0,
"Wrong expression of the Neumann term");
5040 model::varnamelist vl, vl_test1, vl_test2, dl;
5041 bool is_lin = workspace.used_variables(vl, vl_test1, vl_test2, dl, 1);
5043 std::string condition =
"(("+dataH+
")*"+varname
5044 + (datag.size() ?
"-("+datag+
"))":
")");
5045 std::string gamma =
"(("+datagamma0+
")*element_size)";
5046 std::string r =
"(1/"+gamma+
")";
5047 std::string expr =
"("+r+
"*"+condition+
"-("+dataH+
")*("+Neumannterm
5048 +
"))*(("+dataH+
")*Test_"+varname+
")";
5049 if (theta_ != scalar_type(0)) {
5050 std::string derivative_Neumann = workspace.extract_order1_term(varname);
5051 if (derivative_Neumann.size())
5052 expr+=
"-"+theta+
"*"+condition+
"*(("+dataH+
")*(" 5053 +derivative_Neumann+
"))";
5057 "Dirichlet condition with Nitsche's method");
5060 "Dirichlet condition with Nitsche's method");
5074 mutable gmm::row_matrix<model_real_sparse_vector> rB;
5075 mutable gmm::row_matrix<model_complex_sparse_vector> cB;
5077 virtual void real_pre_assembly_in_serial(
const model &md,
size_type ib,
5078 const model::varnamelist &vl,
5079 const model::varnamelist &dl,
5080 const model::mimlist &mims,
5081 model::real_matlist &matl,
5082 model::real_veclist &vecl,
5083 model::real_veclist &,
5085 build_version version)
const {
5086 if (MPI_IS_MASTER()) {
5088 GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
5089 "Pointwize constraints brick has only one term");
5090 GMM_ASSERT1(mims.size() == 0,
5091 "Pointwize constraints brick does not need a mesh_im");
5092 GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2,
5093 "Wrong number of variables for pointwize constraints brick");
5094 bool penalized = (vl.size() == 1);
5098 GMM_ASSERT1(dl.size() == dlsize || dl.size() == dlsize+1,
5099 "Wrong number of data for pointwize constraints brick");
5102 const model_real_plain_vector *COEFF = 0;
5106 GMM_ASSERT1(gmm::vect_size(*COEFF) == 1,
5107 "Data for coefficient should be a scalar");
5110 const model_real_plain_vector &PT = md.
real_variable(dl[ind_pt]);
5111 size_type nb_co = gmm::vect_size(PT) / N;
5113 dim_type ind_unitv = dim_type((Q > 1) ? ind_pt+1 : 0);
5114 const model_real_plain_vector &unitv =md.
real_variable(dl[ind_unitv]);
5115 GMM_ASSERT1((!ind_unitv || gmm::vect_size(unitv) == nb_co * Q),
5116 "Wrong size for vector of unit vectors");
5118 dim_type ind_rhs = dim_type((Q > 1) ? ind_pt+2 : ind_pt+1);
5119 if (dl.size() <
size_type(ind_rhs + 1)) ind_rhs = 0;
5120 const model_real_plain_vector &rhs = md.
real_variable(dl[ind_rhs]);
5121 GMM_ASSERT1((!ind_rhs || gmm::vect_size(rhs) == nb_co),
5122 "Wrong size for vector of rhs");
5124 bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
5125 || (penalized && (md.is_var_newer_than_brick(dl[ind_pt], ib)
5126 || md.is_var_newer_than_brick(dl[ind_unitv], ib)
5127 || md.is_var_newer_than_brick(dl[ind_rhs], ib)));
5129 if (recompute_matrix) {
5130 gmm::row_matrix<model_real_sparse_vector> BB(nb_co*Q, mf_u.
nb_dof());
5131 gmm::clear(rB); gmm::resize(rB, nb_co, mf_u.
nb_dof());
5133 dal::bit_vector dof_untouched;
5137 gmm::copy(gmm::sub_vector(PT, gmm::sub_interval(i*N, N)), pt);
5140 gmm::row_matrix<model_real_sparse_vector> &BBB = ((Q > 1) ? BB : rB);
5141 model_real_plain_vector vv;
5142 interpolation(mf_u, mti, vv, vv, BBB, 1, 1, &dof_untouched);
5143 GMM_ASSERT1(dof_untouched.card() == 0,
5144 "Pointwize constraints : some of the points are outside " 5145 "the mesh: " << dof_untouched);
5150 gmm::add(gmm::scaled(gmm::mat_row(BB, i*Q+q), unitv[i*Q+q]),
5151 gmm::mat_row(rB, i));
5154 gmm::mult(gmm::transposed(rB), rB, matl[0]);
5155 gmm::scale(matl[0], gmm::abs((*COEFF)[0]));
5157 gmm::copy(rB, matl[0]);
5162 gmm::mult(gmm::transposed(rB), rhs, vecl[0]);
5163 gmm::scale(vecl[0], gmm::abs((*COEFF)[0]));
5165 else gmm::copy(rhs, vecl[0]);
5167 else gmm::clear(vecl[0]);
5171 virtual void complex_pre_assembly_in_serial(
const model &md,
size_type ib,
5172 const model::varnamelist &vl,
5173 const model::varnamelist &dl,
5174 const model::mimlist &mims,
5175 model::complex_matlist &matl,
5176 model::complex_veclist &vecl,
5177 model::complex_veclist &,
5179 build_version version)
const {
5180 if (MPI_IS_MASTER()) {
5181 GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
5182 "Pointwize constraints brick only one term");
5183 GMM_ASSERT1(mims.size() == 0,
5184 "Pointwize constraints brick does not need a mesh_im");
5185 GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2,
5186 "Wrong number of variables for pointwize constraints brick");
5187 bool penalized = (vl.size() == 1);
5191 GMM_ASSERT1(dl.size() == dlsize || dl.size() == dlsize+1,
5192 "Wrong number of data for pointwize constraints brick");
5195 const model_complex_plain_vector *COEFF = 0;
5199 GMM_ASSERT1(gmm::vect_size(*COEFF) == 1,
5200 "Data for coefficient should be a scalar");
5204 size_type nb_co = gmm::vect_size(PT) / N;
5206 dim_type ind_unitv = dim_type((Q > 1) ? ind_pt+1 : 0);
5207 const model_complex_plain_vector &unitv
5209 GMM_ASSERT1((!ind_unitv || gmm::vect_size(unitv) == nb_co * Q),
5210 "Wrong size for vector of unit vectors");
5212 dim_type ind_rhs = dim_type((Q > 1) ? ind_pt+2 : ind_pt+1);
5213 if (dl.size() <
size_type(ind_rhs + 1)) ind_rhs = 0;
5214 const model_complex_plain_vector &rhs
5216 GMM_ASSERT1((!ind_rhs || gmm::vect_size(rhs) == nb_co),
5217 "Wrong size for vector of rhs");
5219 bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
5220 || (penalized && (md.is_var_newer_than_brick(dl[ind_pt], ib)
5221 || md.is_var_newer_than_brick(dl[ind_unitv], ib)
5222 || md.is_var_newer_than_brick(dl[ind_rhs], ib)));
5224 if (recompute_matrix) {
5225 gmm::row_matrix<model_complex_sparse_vector>
5226 BB(nb_co*Q,mf_u.
nb_dof());
5227 gmm::clear(cB); gmm::resize(cB, nb_co, mf_u.
nb_dof());
5228 dal::bit_vector dof_untouched;
5232 gmm::copy(gmm::real_part
5233 (gmm::sub_vector(PT, gmm::sub_interval(i*N, N))), pt);
5236 gmm::row_matrix<model_complex_sparse_vector> &BBB = ((Q > 1) ? BB :cB);
5237 model_complex_plain_vector vv;
5238 interpolation(mf_u, mti, vv, vv, BBB, 1, 1, &dof_untouched);
5239 GMM_ASSERT1(dof_untouched.card() == 0,
5240 "Pointwize constraints : some of the points are outside " 5241 "the mesh: " << dof_untouched);
5246 gmm::add(gmm::scaled(gmm::mat_row(BB, i*Q+q), unitv[i*Q+q]),
5247 gmm::mat_row(cB, i));
5251 gmm::mult(gmm::transposed(cB), cB, matl[0]);
5252 gmm::scale(matl[0], gmm::abs((*COEFF)[0]));
5254 gmm::copy(cB, matl[0]);
5260 gmm::mult(gmm::transposed(cB), rhs, vecl[0]);
5261 gmm::scale(vecl[0], gmm::abs((*COEFF)[0]));
5263 else gmm::copy(rhs, vecl[0]);
5265 else gmm::clear(vecl[0]);
5269 virtual std::string declare_volume_assembly_string
5271 const model::varnamelist &)
const {
5272 return std::string();
5275 pointwise_constraints_brick(
bool penalized) {
5276 set_flags(penalized ?
"Pointwise cosntraints with penalization brick" 5277 :
"Pointwise cosntraints with multipliers brick",
5288 scalar_type penalisation_coeff,
const std::string &dataname_pt,
5289 const std::string &dataname_unitv,
const std::string &dataname_val) {
5290 std::string coeffname = md.
new_name(
"penalization_on_" + varname);
5296 pbrick pbr = std::make_shared<pointwise_constraints_brick>(
true);
5298 tl.push_back(model::term_description(varname, varname,
true));
5299 model::varnamelist vl(1, varname);
5300 model::varnamelist dl(1, coeffname);
5301 dl.push_back(dataname_pt);
5303 if (mf_u.
get_qdim() > 1) dl.push_back(dataname_unitv);
5304 if (dataname_val.size() > 0) dl.push_back(dataname_val);
5310 const std::string &multname,
const std::string &dataname_pt,
5311 const std::string &dataname_unitv,
const std::string &dataname_val) {
5312 pbrick pbr = std::make_shared<pointwise_constraints_brick>(
false);
5314 tl.push_back(model::term_description(multname, varname,
true));
5315 model::varnamelist vl(1, varname);
5316 vl.push_back(multname);
5317 model::varnamelist dl(1, dataname_pt);
5319 if (mf_u.
get_qdim() > 1) dl.push_back(dataname_unitv);
5320 if (dataname_val.size() > 0) dl.push_back(dataname_val);
5325 (
model &md,
const std::string &varname,
const std::string &dataname_pt,
5326 const std::string &dataname_unitv,
const std::string &dataname_val) {
5327 std::string multname = md.
new_name(
"mult_on_" + varname);
5335 (md, varname, multname, dataname_pt, dataname_unitv, dataname_val);
5348 const model::varnamelist &vl,
5349 const model::varnamelist &dl,
5350 const model::mimlist &mims,
5351 model::real_matlist &matl,
5352 model::real_veclist &,
5353 model::real_veclist &,
5355 build_version)
const {
5356 GMM_ASSERT1(matl.size() == 1,
5357 "Helmholtz brick has one and only one term");
5358 GMM_ASSERT1(mims.size() == 1,
5359 "Helmholtz brick need one and only one mesh_im");
5360 GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
5361 "Wrong number of variables for Helmholtz brick");
5364 const mesh &m = mf_u.linked_mesh();
5366 GMM_ASSERT1(Q == 1,
"Helmholtz brick is only for scalar field, sorry.");
5367 const mesh_im &mim = *mims[0];
5370 m.intersect_with_mpi_region(rg);
5371 const model_real_plain_vector *A = &(md.
real_variable(dl[0]));
5373 s = gmm::vect_size(*A);
5377 GMM_TRACE2(
"Stiffness matrix assembly for Helmholtz problem");
5378 gmm::clear(matl[0]);
5379 model_real_plain_vector A2(gmm::vect_size(*A));
5380 for (
size_type i=0; i < gmm::vect_size(*A); ++i)
5381 A2[i] = gmm::sqr((*A)[i]);
5387 GMM_ASSERT1(
false,
"Bad format Helmholtz brick coefficient");
5390 virtual void asm_complex_tangent_terms(
const model &md,
size_type,
5391 const model::varnamelist &vl,
5392 const model::varnamelist &dl,
5393 const model::mimlist &mims,
5394 model::complex_matlist &matl,
5395 model::complex_veclist &,
5396 model::complex_veclist &,
5398 build_version)
const {
5399 GMM_ASSERT1(matl.size() == 1,
5400 "Helmholtz brick has one and only one term");
5401 GMM_ASSERT1(mims.size() == 1,
5402 "Helmholtz brick need one and only one mesh_im");
5403 GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
5404 "Wrong number of variables for Helmholtz brick");
5407 const mesh &m = mf_u.linked_mesh();
5409 GMM_ASSERT1(Q == 1,
"Helmholtz brick is only for scalar field, sorry.");
5410 const mesh_im &mim = *mims[0];
5413 m.intersect_with_mpi_region(rg);
5416 s = gmm::vect_size(*A);
5420 GMM_TRACE2(
"Stiffness matrix assembly for Helmholtz problem");
5421 gmm::clear(matl[0]);
5422 model_complex_plain_vector A2(gmm::vect_size(*A));
5423 for (
size_type i=0; i < gmm::vect_size(*A); ++i)
5424 A2[i] = gmm::sqr((*A)[i]);
5430 GMM_ASSERT1(
false,
"Bad format Helmholtz brick coefficient");
5434 set_flags(
"Helmholtz",
true ,
5442 const std::string &varname,
5443 const std::string &dataexpr,
5446 pbrick pbr = std::make_shared<Helmholtz_brick>();
5448 tl.push_back(model::term_description(varname, varname,
true));
5449 return md.
add_brick(pbr, model::varnamelist(1, varname),
5450 model::varnamelist(1, dataexpr), tl,
5451 model::mimlist(1, &mim), region);
5453 std::string test_varname
5454 =
"Test_" + sup_previous_and_dot_to_varname(varname);
5455 std::string expr =
"Grad_"+varname+
".Grad_"+test_varname
5456 +
" + sqr("+dataexpr+
")*"+varname+
"*"+test_varname;
5462 "Helmholtz (nonlinear)");
5478 const model::varnamelist &vl,
5479 const model::varnamelist &dl,
5480 const model::mimlist &mims,
5481 model::real_matlist &matl,
5482 model::real_veclist &,
5483 model::real_veclist &,
5485 build_version)
const {
5486 GMM_ASSERT1(matl.size() == 1,
5487 "Fourier-Robin brick has one and only one term");
5488 GMM_ASSERT1(mims.size() == 1,
5489 "Fourier-Robin brick need one and only one mesh_im");
5490 GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
5491 "Wrong number of variables for Fourier-Robin brick");
5494 const mesh &m = mf_u.linked_mesh();
5496 const mesh_im &mim = *mims[0];
5499 m.intersect_with_mpi_region(rg);
5500 const model_real_plain_vector *A = &(md.
real_variable(dl[0]));
5502 s = gmm::vect_size(*A);
5504 GMM_ASSERT1(s == Q*Q,
5505 "Bad format Fourier-Robin brick coefficient");
5507 GMM_TRACE2(
"Fourier-Robin term assembly");
5508 gmm::clear(matl[0]);
5512 asm_homogeneous_qu_term(matl[0], mim, mf_u, *A, rg);
5515 virtual void asm_complex_tangent_terms(
const model &md,
size_type,
5516 const model::varnamelist &vl,
5517 const model::varnamelist &dl,
5518 const model::mimlist &mims,
5519 model::complex_matlist &matl,
5520 model::complex_veclist &,
5521 model::complex_veclist &,
5523 build_version)
const {
5524 GMM_ASSERT1(matl.size() == 1,
5525 "Fourier-Robin brick has one and only one term");
5526 GMM_ASSERT1(mims.size() == 1,
5527 "Fourier-Robin brick need one and only one mesh_im");
5528 GMM_ASSERT1(vl.size() == 1 && dl.size() == 1,
5529 "Wrong number of variables for Fourier-Robin brick");
5532 const mesh &m = mf_u.linked_mesh();
5534 const mesh_im &mim = *mims[0];
5537 m.intersect_with_mpi_region(rg);
5540 s = gmm::vect_size(*A);
5542 GMM_ASSERT1(s == Q*Q,
5543 "Bad format Fourier-Robin brick coefficient");
5545 GMM_TRACE2(
"Fourier-Robin term assembly");
5546 gmm::clear(matl[0]);
5550 asm_homogeneous_qu_term(matl[0], mim, mf_u, *A, rg);
5553 Fourier_Robin_brick() {
5554 set_flags(
"Fourier Robin condition",
true ,
5563 const std::string &varname,
5564 const std::string &dataexpr,
5567 pbrick pbr = std::make_shared<Fourier_Robin_brick>();
5569 tl.push_back(model::term_description(varname, varname,
true));
5570 return md.
add_brick(pbr, model::varnamelist(1, varname),
5571 model::varnamelist(1, dataexpr), tl,
5572 model::mimlist(1, &mim), region);
5574 std::string test_varname
5575 =
"Test_" + sup_previous_and_dot_to_varname(varname);
5576 std::string expr =
"(("+dataexpr+
")*"+varname+
")."+test_varname;
5578 "Fourier-Robin",
true);
5581 "Fourier-Robin (nonlinear)");
5594 model_real_sparse_matrix rB;
5595 model_complex_sparse_matrix cB;
5596 model_real_plain_vector rL;
5597 model_complex_plain_vector cL;
5601 struct constraint_brick :
public have_private_data_brick {
5603 virtual void real_pre_assembly_in_serial(
const model &md,
size_type,
5604 const model::varnamelist &vl,
5605 const model::varnamelist &dl,
5606 const model::mimlist &mims,
5607 model::real_matlist &matl,
5608 model::real_veclist &vecl,
5609 model::real_veclist &,
5611 if (MPI_IS_MASTER()) {
5613 GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
5614 "Constraint brick has one and only one term");
5615 GMM_ASSERT1(mims.size() == 0,
5616 "Constraint brick need no mesh_im");
5617 GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2 && dl.size() <= 1,
5618 "Wrong number of variables for constraint brick");
5620 bool penalized = (vl.size() == 1);
5621 const model_real_plain_vector *COEFF = 0;
5623 bool has_data = (nameL.compare(
"") != 0);
5625 GMM_ASSERT1(nameL.compare(dl.back()) == 0 &&
5628 const model_real_plain_vector &
5633 GMM_ASSERT1(gmm::vect_size(*COEFF) == 1,
5634 "Data for coefficient should be a scalar");
5636 gmm::mult(gmm::transposed(rB),
5637 gmm::scaled(rrL, gmm::abs((*COEFF)[0])), vecl[0]);
5638 gmm::mult(gmm::transposed(rB),
5639 gmm::scaled(rB, gmm::abs((*COEFF)[0])), matl[0]);
5641 gmm::copy(rrL, vecl[0]);
5642 gmm::copy(rB, matl[0]);
5647 virtual void complex_pre_assembly_in_serial(
const model &md,
size_type,
5648 const model::varnamelist &vl,
5649 const model::varnamelist &dl,
5650 const model::mimlist &mims,
5651 model::complex_matlist &matl,
5652 model::complex_veclist &vecl,
5653 model::complex_veclist &,
5655 build_version)
const {
5656 if (MPI_IS_MASTER()) {
5658 GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
5659 "Constraint brick has one and only one term");
5660 GMM_ASSERT1(mims.size() == 0,
5661 "Constraint brick need no mesh_im");
5662 GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2 && dl.size() <= 1,
5663 "Wrong number of variables for constraint brick");
5665 bool penalized = (vl.size() == 1);
5666 const model_complex_plain_vector *COEFF = 0;
5668 bool has_data = (nameL.compare(
"") != 0);
5670 GMM_ASSERT1(nameL.compare(dl.back()) == 0 &&
5673 const model_complex_plain_vector &
5678 GMM_ASSERT1(gmm::vect_size(*COEFF) == 1,
5679 "Data for coefficient should be a scalar");
5681 gmm::mult(gmm::transposed(cB),
5682 gmm::scaled(ccL, gmm::abs((*COEFF)[0])), vecl[0]);
5683 gmm::mult(gmm::transposed(cB),
5684 gmm::scaled(cB, gmm::abs((*COEFF)[0])), matl[0]);
5686 gmm::copy(ccL, vecl[0]);
5687 gmm::copy(cB, matl[0]);
5692 virtual std::string declare_volume_assembly_string
5694 const model::varnamelist &)
const {
5695 return std::string();
5698 constraint_brick(
bool penalized) {
5699 set_flags(penalized ?
"Constraint with penalization brick" 5700 :
"Constraint with multipliers brick",
5709 model_real_sparse_matrix &set_private_data_brick_real_matrix
5711 pbrick pbr = md.brick_pointer(indbrick);
5713 have_private_data_brick *p =
dynamic_cast<have_private_data_brick *
> 5715 GMM_ASSERT1(p,
"Wrong type of brick");
5719 model_real_plain_vector &set_private_data_brick_real_rhs
5721 pbrick pbr = md.brick_pointer(indbrick);
5723 have_private_data_brick *p =
dynamic_cast<have_private_data_brick *
> 5725 GMM_ASSERT1(p,
"Wrong type of brick");
5726 if (p->nameL.compare(
"") != 0) GMM_WARNING1(
"Rhs already set by data name");
5730 model_complex_sparse_matrix &set_private_data_brick_complex_matrix
5732 pbrick pbr = md.brick_pointer(indbrick);
5734 have_private_data_brick *p =
dynamic_cast<have_private_data_brick *
> 5736 GMM_ASSERT1(p,
"Wrong type of brick");
5740 model_complex_plain_vector &set_private_data_brick_complex_rhs
5742 pbrick pbr = md.brick_pointer(indbrick);
5744 have_private_data_brick *p =
dynamic_cast<have_private_data_brick *
> 5746 GMM_ASSERT1(p,
"Wrong type of brick");
5747 if (p->nameL.compare(
"") != 0) GMM_WARNING1(
"Rhs already set by data name");
5751 void set_private_data_rhs
5753 pbrick pbr = md.brick_pointer(indbrick);
5755 have_private_data_brick *p =
dynamic_cast<have_private_data_brick *
> 5757 GMM_ASSERT1(p,
"Wrong type of brick");
5758 if (p->nameL.compare(varname) != 0) {
5759 model::varnamelist dl = md.datanamelist_of_brick(indbrick);
5760 if (p->nameL.compare(
"") == 0) dl.push_back(varname);
5761 else dl.back() = varname;
5767 size_type add_constraint_with_penalization
5768 (
model &md,
const std::string &varname, scalar_type penalisation_coeff) {
5769 std::string coeffname = md.
new_name(
"penalization_on_" + varname);
5775 pbrick pbr = std::make_shared<constraint_brick>(
true);
5777 tl.push_back(model::term_description(varname, varname,
true));
5778 model::varnamelist vl(1, varname);
5779 model::varnamelist dl(1, coeffname);
5783 size_type add_constraint_with_multipliers
5784 (
model &md,
const std::string &varname,
const std::string &multname) {
5785 pbrick pbr = std::make_shared<constraint_brick>(
false);
5787 tl.push_back(model::term_description(multname, varname,
true));
5788 model::varnamelist vl(1, varname);
5789 vl.push_back(multname);
5790 model::varnamelist dl;
5801 struct explicit_matrix_brick :
public have_private_data_brick {
5803 virtual void real_pre_assembly_in_serial(
const model &,
size_type,
5804 const model::varnamelist &vl,
5805 const model::varnamelist &dl,
5806 const model::mimlist &mims,
5807 model::real_matlist &matl,
5808 model::real_veclist &vecl,
5809 model::real_veclist &,
5811 GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
5812 "Explicit matrix has one and only one term");
5813 GMM_ASSERT1(mims.size() == 0,
"Explicit matrix need no mesh_im");
5814 GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2 && dl.size() == 0,
5815 "Wrong number of variables for explicit matrix brick");
5816 gmm::copy(rB, matl[0]);
5819 virtual void complex_pre_assembly_in_serial(
const model &,
size_type,
5820 const model::varnamelist &vl,
5821 const model::varnamelist &dl,
5822 const model::mimlist &mims,
5823 model::complex_matlist &matl,
5824 model::complex_veclist &vecl,
5825 model::complex_veclist &,
5827 build_version)
const {
5828 GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
5829 "Explicit matrix has one and only one term");
5830 GMM_ASSERT1(mims.size() == 0,
"Explicit matrix need no mesh_im");
5831 GMM_ASSERT1(vl.size() >= 1 && vl.size() <= 2 && dl.size() == 0,
5832 "Wrong number of variables for explicit matrix brick");
5833 gmm::copy(cB, matl[0]);
5836 virtual std::string declare_volume_assembly_string
5838 const model::varnamelist &)
const {
5839 return std::string();
5842 explicit_matrix_brick(
bool symmetric_,
bool coercive_) {
5843 set_flags(
"Explicit matrix brick",
5845 symmetric_ , coercive_ ,
5852 (
model &md,
const std::string &varname1,
const std::string &varname2,
5853 bool issymmetric,
bool iscoercive) {
5854 pbrick pbr = std::make_shared<explicit_matrix_brick>(issymmetric,
5857 tl.push_back(model::term_description(varname1, varname2, issymmetric));
5858 model::varnamelist vl(1, varname1);
5859 vl.push_back(varname2);
5860 model::varnamelist dl;
5870 struct explicit_rhs_brick :
public have_private_data_brick {
5872 virtual void real_pre_assembly_in_serial(
const model &,
size_type,
5873 const model::varnamelist &vl,
5874 const model::varnamelist &dl,
5875 const model::mimlist &mims,
5876 model::real_matlist &matl,
5877 model::real_veclist &vecl,
5878 model::real_veclist &,
5880 if (MPI_IS_MASTER()) {
5881 GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
5882 "Explicit rhs has one and only one term");
5883 GMM_ASSERT1(mims.size() == 0,
"Explicit rhs need no mesh_im");
5884 GMM_ASSERT1(vl.size() == 1 && dl.size() == 0,
5885 "Wrong number of variables for explicit rhs brick");
5886 gmm::copy(rL, vecl[0]);
5890 virtual void complex_pre_assembly_in_serial(
const model &,
size_type,
5891 const model::varnamelist &vl,
5892 const model::varnamelist &dl,
5893 const model::mimlist &mims,
5894 model::complex_matlist &matl,
5895 model::complex_veclist &vecl,
5896 model::complex_veclist &,
5898 build_version)
const {
5899 if (MPI_IS_MASTER()) {
5900 GMM_ASSERT1(vecl.size() == 1 && matl.size() == 1,
5901 "Explicit rhs has one and only one term");
5902 GMM_ASSERT1(mims.size() == 0,
"Explicit rhs need no mesh_im");
5903 GMM_ASSERT1(vl.size() == 1 && dl.size() == 0,
5904 "Wrong number of variables for explicit rhs brick");
5905 gmm::copy(cL, vecl[0]);
5910 virtual std::string declare_volume_assembly_string
5912 const model::varnamelist &)
const {
5913 return std::string();
5916 explicit_rhs_brick() {
5917 set_flags(
"Explicit rhs brick",
5927 (
model &md,
const std::string &varname) {
5928 pbrick pbr = std::make_shared<explicit_rhs_brick>();
5930 tl.push_back(model::term_description(varname));
5931 model::varnamelist vl(1, varname);
5932 model::varnamelist dl;
5943 struct iso_lin_elasticity_new_brick :
public virtual_brick {
5945 std::string expr, dataname3;
5948 const model::varnamelist &vl,
5949 const model::varnamelist &dl,
5950 const model::mimlist &mims,
5951 model::real_matlist &matl,
5952 model::real_veclist &vecl,
5953 model::real_veclist &,
5955 build_version version)
const override {
5956 GMM_ASSERT1(vl.size() == 1,
"Linearized isotropic elasticity brick " 5957 "has one and only one variable");
5958 GMM_ASSERT1(matl.size() == 1,
"Linearized isotropic elasticity brick " 5959 "has one and only one term");
5960 GMM_ASSERT1(mims.size() == 1,
"Linearized isotropic elasticity brick " 5961 "needs one and only one mesh_im");
5963 bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0);
5964 for (
size_type i = 0; i < dl.size(); ++i) {
5965 recompute_matrix = recompute_matrix ||
5966 md.is_var_newer_than_brick(dl[i], ib);
5969 if (recompute_matrix) {
5971 ga_workspace workspace(md,
true);
5972 workspace.add_expression(expr, *(mims[0]), region);
5973 GMM_TRACE2(name <<
": generic matrix assembly");
5974 model::varnamelist vlmd; md.variable_list(vlmd);
5975 for (
size_type i = 0; i < vlmd.size(); ++i)
5976 if (md.is_disabled_variable(vlmd[i]))
5977 nbgdof = std::max(nbgdof,
5978 workspace.interval_of_variable(vlmd[i]).last());
5979 model_real_sparse_matrix R(nbgdof, nbgdof);
5980 workspace.set_assembled_matrix(R);
5981 workspace.assembly(2);
5982 scalar_type alpha = scalar_type(1)
5983 / (workspace.factor_of_variable(vl[0]));
5984 gmm::sub_interval I = workspace.interval_of_variable(vl[0]);
5985 gmm::copy(gmm::scaled(gmm::sub_matrix(R, I, I), alpha),
5989 if (dataname3.size()) {
5993 gmm::clear(vecl[0]);
6002 const model::varnamelist &,
6003 const model::varnamelist &,
6004 const model::mimlist &,
6005 model::real_matlist &,
6006 model::real_veclist &vecl,
6007 model::real_veclist &,
6009 build_version)
const override {
6010 md.add_external_load(ib, gmm::vect_norm1(vecl[0]));
6014 virtual std::string declare_volume_assembly_string
6016 const model::varnamelist &)
const {
6020 iso_lin_elasticity_new_brick(
const std::string &expr_,
6021 const std::string &dataname3_) {
6022 expr = expr_; dataname3 = dataname3_;
6023 set_flags(
"Linearized isotropic elasticity",
true ,
6033 const std::string &dataexpr1,
const std::string &dataexpr2,
6034 size_type region,
const std::string &dataname3) {
6035 std::string test_varname
6036 =
"Test_" + sup_previous_and_dot_to_varname(varname);
6038 std::string expr1 =
"((("+dataexpr1+
")*(Div_"+varname+
"-Div_"+dataname3
6039 +
"))*Id(meshdim)+(2*("+dataexpr2+
"))*(Sym(Grad_"+varname
6040 +
")-Sym(Grad_"+dataname3+
"))):Grad_" +test_varname;
6041 std::string expr2 =
"(Div_"+varname+
"*(("+dataexpr1+
")*Id(meshdim))" 6042 +
"+(2*("+dataexpr2+
"))*Sym(Grad_"+varname+
")):Grad_"+test_varname;
6044 ga_workspace workspace(md,
true);
6045 workspace.add_expression(expr2, mim, region);
6046 model::varnamelist vl, vl_test1, vl_test2, dl;
6047 bool is_lin = workspace.used_variables(vl, vl_test1, vl_test2, dl, 2);
6050 pbrick pbr = std::make_shared<iso_lin_elasticity_new_brick>
6053 tl.push_back(model::term_description(varname,
6054 sup_previous_and_dot_to_varname(varname),
true));
6055 if (dataname3.size()) dl.push_back(dataname3);
6056 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
6058 return add_nonlinear_generic_assembly_brick
6059 (md, mim, dataname3.size() ? expr1 : expr2, region,
false,
false,
6060 "Linearized isotropic elasticity (with nonlinear dependance)");
6066 const std::string &data_E,
const std::string &data_nu,
6068 std::string test_varname
6069 =
"Test_" + sup_previous_and_dot_to_varname(varname);
6071 std::string mu =
"(("+data_E+
")/(2*(1+("+data_nu+
"))))";
6072 std::string lambda =
"(("+data_E+
")*("+data_nu+
")/((1+("+data_nu+
"))*(1-2*(" 6074 std::string expr = lambda+
"*Div_"+varname+
"*Div_"+test_varname
6075 +
"+"+mu+
"*(Grad_"+varname+
"+Grad_"+varname+
"'):Grad_"+test_varname;
6077 ga_workspace workspace(md,
true);
6078 workspace.add_expression(expr, mim, region);
6079 model::varnamelist vl, vl_test1, vl_test2, dl;
6080 bool is_lin = workspace.used_variables(vl, vl_test1, vl_test2, dl, 2);
6084 "Linearized isotropic elasticity");
6087 (md, mim, expr, region,
false,
false,
6088 "Linearized isotropic elasticity (with nonlinear dependance)");
6094 const std::string &data_E,
const std::string &data_nu,
6096 std::string test_varname
6097 =
"Test_" + sup_previous_and_dot_to_varname(varname);
6100 GMM_ASSERT1(mfu,
"The variable should be a fem variable");
6103 std::string mu =
"(("+data_E+
")/(2*(1+("+data_nu+
"))))";
6104 std::string lambda =
"(("+data_E+
")*("+data_nu+
")/((1+("+data_nu+
"))*(1-2*(" 6107 lambda =
"(("+data_E+
")*("+data_nu+
")/((1-sqr("+data_nu+
"))))";
6108 std::string expr = lambda+
"*Div_"+varname+
"*Div_"+test_varname
6109 +
"+"+mu+
"*(Grad_"+varname+
"+Grad_"+varname+
"'):Grad_"+test_varname;
6111 ga_workspace workspace(md,
true);
6112 workspace.add_expression(expr, mim, region);
6113 model::varnamelist vl, vl_test1, vl_test2, dl;
6114 bool is_lin = workspace.used_variables(vl, vl_test1, vl_test2, dl, 2);
6118 "Linearized isotropic elasticity");
6121 (md, mim, expr, region,
false,
false,
6122 "Linearized isotropic elasticity (with nonlinear dependance)");
6127 void compute_isotropic_linearized_Von_Mises_or_Tresca
6128 (
model &md,
const std::string &varname,
const std::string &data_lambda,
6129 const std::string &data_mu,
const mesh_fem &mf_vm,
6130 model_real_plain_vector &VM,
bool tresca) {
6135 const model_real_plain_vector *lambda=&(md.
real_variable(data_lambda));
6137 const model_real_plain_vector *mu = &(md.
real_variable(data_mu));
6140 if (mf_lambda) sl = sl * mf_lambda->
get_qdim() / mf_lambda->
nb_dof();
6144 GMM_ASSERT1(sl == 1 && sm == 1,
"Bad format for Lame coefficients");
6145 GMM_ASSERT1(mf_lambda == mf_mu,
6146 "The two Lame coefficients should be described on the same " 6147 "finite element method.");
6152 *mf_lambda, *lambda,
6157 model_real_plain_vector LAMBDA(mf_lambda->
nb_dof(), (*lambda)[0]);
6158 model_real_plain_vector MU(mf_lambda->
nb_dof(), (*mu)[0]);
6169 std::string sigma_d=
"("+data_mu+
")*(Grad_"+varname+
"+Grad_"+varname+
"')";
6170 std::string expr =
"sqrt(3/2)*Norm(Deviator("+sigma_d+
"))";
6171 ga_interpolation_Lagrange_fem(md, expr, mf_vm, VM);
6177 (
model &md,
const std::string &varname,
const std::string &data_E,
6178 const std::string &data_nu,
const mesh_fem &mf_vm,
6179 model_real_plain_vector &VM) {
6183 std::string mu =
"(("+data_E+
")/(2*(1+("+data_nu+
"))))";
6186 std::string sigma_d = mu+
"*(Grad_"+varname+
"+Grad_"+varname+
"')";
6187 std::string expr =
"sqrt(3/2)*Norm(Deviator("+sigma_d+
"))";
6188 ga_interpolation_Lagrange_fem(md, expr, mf_vm, VM);
6192 (
model &md,
const std::string &varname,
const std::string &data_E,
6193 const std::string &data_nu,
const mesh_fem &mf_vm,
6194 model_real_plain_vector &VM) {
6203 std::string mu =
"(("+data_E+
")/(2*(1+("+data_nu+
"))))";
6206 std::string sigma_d = mu+
"*(Grad_"+varname+
"+Grad_"+varname+
"')";
6207 std::string expr =
"sqrt(3/2)*Norm(Deviator("+sigma_d+
"))";
6208 ga_interpolation_Lagrange_fem(md, expr, mf_vm, VM);
6218 struct linear_incompressibility_brick :
public virtual_brick {
6221 const model::varnamelist &vl,
6222 const model::varnamelist &dl,
6223 const model::mimlist &mims,
6224 model::real_matlist &matl,
6225 model::real_veclist &,
6226 model::real_veclist &,
6228 build_version)
const {
6230 GMM_ASSERT1((matl.size() == 1 && dl.size() == 0)
6231 || (matl.size() == 2 && dl.size() == 1),
6232 "Wrong term and/or data number for Linear incompressibility " 6234 GMM_ASSERT1(mims.size() == 1,
"Linear incompressibility brick need one " 6235 "and only one mesh_im");
6236 GMM_ASSERT1(vl.size() == 2,
"Wrong number of variables for linear " 6237 "incompressibility brick");
6239 bool penalized = (dl.size() == 1);
6242 const mesh_im &mim = *mims[0];
6243 const model_real_plain_vector *COEFF = 0;
6251 GMM_ASSERT1(s == 1,
"Bad format for the penalization parameter");
6257 GMM_TRACE2(
"Stokes term assembly");
6258 gmm::clear(matl[0]);
6262 gmm::clear(matl[1]);
6265 gmm::scale(matl[1], scalar_type(-1));
6269 gmm::scale(matl[1], -(*COEFF)[0]);
6276 virtual void real_post_assembly_in_serial(
const model &,
size_type,
6277 const model::varnamelist &,
6278 const model::varnamelist &,
6279 const model::mimlist &,
6280 model::real_matlist &,
6281 model::real_veclist &,
6282 model::real_veclist &,
6284 build_version)
const 6288 linear_incompressibility_brick() {
6289 set_flags(
"Linear incompressibility brick",
6299 const std::string &multname,
size_type region,
6300 const std::string &dataexpr) {
6302 pbrick pbr = std::make_shared<linear_incompressibility_brick>();
6304 tl.push_back(model::term_description(multname, varname,
true));
6305 model::varnamelist vl(1, varname);
6306 vl.push_back(multname);
6307 model::varnamelist dl;
6308 if (dataname.size()) {
6309 dl.push_back(dataexpr);
6310 tl.push_back(model::term_description(multname, multname,
true));
6312 return md.
add_brick(pbr, vl, dl, tl, model::mimlist(1, &mim), region);
6314 std::string test_varname
6315 =
"Test_" + sup_previous_and_dot_to_varname(varname);
6316 std::string test_multname
6317 =
"Test_" + sup_previous_and_dot_to_varname(multname);
6319 if (dataexpr.size())
6320 expr =
"-"+multname+
"*Div_"+test_varname +
"-"+test_multname
6321 +
"*Div_"+varname+
"+(("+dataexpr+
")*"+multname+
")*"+test_multname;
6323 expr =
"-"+multname+
"*Div_"+test_varname +
"-"+test_multname
6326 "Linear incompressibility",
true);
6329 (md, mim, expr, region,
false,
false,
6330 "Linear incompressibility (with nonlinear dependance)");
6346 const model::varnamelist &vl,
6347 const model::varnamelist &dl,
6348 const model::mimlist &mims,
6349 model::real_matlist &matl,
6350 model::real_veclist &,
6351 model::real_veclist &,
6353 build_version)
const {
6354 GMM_ASSERT1(matl.size() == 1,
6355 "Mass brick has one and only one term");
6356 GMM_ASSERT1(mims.size() == 1,
6357 "Mass brick need one and only one mesh_im");
6358 GMM_ASSERT1(vl.size() == 1 && dl.size() <= 1,
6359 "Wrong number of variables for mass brick");
6362 const mesh &m = mf_u.linked_mesh();
6363 const mesh_im &mim = *mims[0];
6365 m.intersect_with_mpi_region(rg);
6368 const model_real_plain_vector *rho = 0;
6375 GMM_ASSERT1(sl == 1,
"Bad format of mass brick coefficient");
6378 GMM_TRACE2(
"Mass matrix assembly");
6379 gmm::clear(matl[0]);
6380 if (dl.size() && mf_rho) {
6384 if (dl.size()) gmm::scale(matl[0], (*rho)[0]);
6388 virtual void asm_complex_tangent_terms(
const model &md,
size_type,
6389 const model::varnamelist &vl,
6390 const model::varnamelist &dl,
6391 const model::mimlist &mims,
6392 model::complex_matlist &matl,
6393 model::complex_veclist &,
6394 model::complex_veclist &,
6396 build_version)
const {
6397 GMM_ASSERT1(matl.size() == 1,
6398 "Mass brick has one and only one term");
6399 GMM_ASSERT1(mims.size() == 1,
6400 "Mass brick need one and only one mesh_im");
6401 GMM_ASSERT1(vl.size() == 1 && dl.size() <= 1,
6402 "Wrong number of variables for mass brick");
6405 const mesh &m = mf_u.linked_mesh();
6406 const mesh_im &mim = *mims[0];
6408 m.intersect_with_mpi_region(rg);
6411 const model_complex_plain_vector *rho = 0;
6418 GMM_ASSERT1(sl == 1,
"Bad format of mass brick coefficient");
6421 GMM_TRACE2(
"Mass matrix assembly");
6422 gmm::clear(matl[0]);
6423 if (dl.size() && mf_rho) {
6427 if (dl.size()) gmm::scale(matl[0], (*rho)[0]);
6431 virtual std::string declare_volume_assembly_string
6433 const model::varnamelist &)
const {
6434 return std::string();
6438 set_flags(
"Mass brick",
true ,
6448 const std::string &dataexpr_rho,
size_type region) {
6450 pbrick pbr = std::make_shared<mass_brick>();
6452 tl.push_back(model::term_description(varname, varname,
true));
6453 model::varnamelist dl;
6454 if (dataexpr_rho.size())
6455 dl.push_back(dataexpr_rho);
6456 return md.
add_brick(pbr, model::varnamelist(1, varname), dl, tl,
6457 model::mimlist(1, &mim), region);
6459 std::string test_varname
6460 =
"Test_" + sup_previous_and_dot_to_varname(varname);
6462 if (dataexpr_rho.size())
6463 expr =
"(("+dataexpr_rho+
")*"+varname+
")."+test_varname;
6465 expr = varname+
"."+test_varname;
6467 "Mass matrix",
true);
6470 "Mass matrix (nonlinear)");
6491 virtual void asm_real_tangent_terms(
const model &md,
size_type ib,
6492 const model::varnamelist &vl,
6493 const model::varnamelist &dl,
6494 const model::mimlist &mims,
6495 model::real_matlist &matl,
6496 model::real_veclist &vecl,
6497 model::real_veclist &,
6499 build_version version)
const {
6500 GMM_ASSERT1(matl.size() == 1,
6501 "Basic d/dt brick has one and only one term");
6502 GMM_ASSERT1(mims.size() == 1,
6503 "Basic d/dt brick need one and only one mesh_im");
6504 GMM_ASSERT1(vl.size() == 1 && dl.size() >= 2 && dl.size() <= 3,
6505 "Wrong number of variables for basic d/dt brick");
6509 bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
6510 || (md.is_var_newer_than_brick(dl[1], ib));
6512 recompute_matrix = recompute_matrix ||
6513 md.is_var_newer_than_brick(dl[2], ib);
6516 if (recompute_matrix) {
6519 const mesh_im &mim = *mims[0];
6521 m.intersect_with_mpi_region(rg);
6523 const model_real_plain_vector &dt = md.
real_variable(dl[1]);
6524 GMM_ASSERT1(gmm::vect_size(dt) == 1,
"Bad format for time step");
6527 const model_real_plain_vector *rho = 0;
6529 if (dl.size() > 2) {
6534 GMM_ASSERT1(sl == 1,
"Bad format for density");
6537 GMM_TRACE2(
"Mass matrix assembly for d_on_dt brick");
6538 if (dl.size() > 2 && mf_rho) {
6539 gmm::clear(matl[0]);
6541 gmm::scale(matl[0], scalar_type(1) / dt[0]);
6543 gmm::clear(matl[0]);
6545 if (dl.size() > 2) gmm::scale(matl[0], (*rho)[0] / dt[0]);
6546 else gmm::scale(matl[0], scalar_type(1) / dt[0]);
6552 virtual void asm_complex_tangent_terms(
const model &md,
size_type ib,
6553 const model::varnamelist &vl,
6554 const model::varnamelist &dl,
6555 const model::mimlist &mims,
6556 model::complex_matlist &matl,
6557 model::complex_veclist &vecl,
6558 model::complex_veclist &,
6560 build_version version)
const {
6561 GMM_ASSERT1(matl.size() == 1,
6562 "Basic d/dt brick has one and only one term");
6563 GMM_ASSERT1(mims.size() == 1,
6564 "Basic d/dt brick need one and only one mesh_im");
6565 GMM_ASSERT1(vl.size() == 1 && dl.size() >= 2 && dl.size() <= 3,
6566 "Wrong number of variables for basic d/dt brick");
6570 bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0)
6571 || (md.is_var_newer_than_brick(dl[1], ib));
6573 recompute_matrix = recompute_matrix ||
6574 md.is_var_newer_than_brick(dl[2], ib);
6576 if (recompute_matrix) {
6579 const mesh_im &mim = *mims[0];
6582 m.intersect_with_mpi_region(rg);
6585 GMM_ASSERT1(gmm::vect_size(dt) == 1,
"Bad format for time step");
6588 const model_complex_plain_vector *rho = 0;
6590 if (dl.size() > 2) {
6595 GMM_ASSERT1(sl == 1,
"Bad format for density");
6598 GMM_TRACE2(
"Mass matrix assembly for d_on_dt brick");
6599 if (dl.size() > 2 && mf_rho) {
6600 gmm::clear(matl[0]);
6602 gmm::scale(matl[0], scalar_type(1) / dt[0]);
6604 gmm::clear(matl[0]);
6606 if (dl.size() > 2) gmm::scale(matl[0], (*rho)[0] / dt[0]);
6607 else gmm::scale(matl[0], scalar_type(1) / dt[0]);
6613 virtual std::string declare_volume_assembly_string
6615 const model::varnamelist &)
const {
6616 return std::string();
6619 basic_d_on_dt_brick() {
6620 set_flags(
"Basic d/dt brick",
true ,
6630 const std::string &dataname_dt,
const std::string &dataname_rho,
6632 pbrick pbr = std::make_shared<basic_d_on_dt_brick>();
6634 tl.push_back(model::term_description(varname, varname,
true));
6635 model::varnamelist dl(1, varname);
6636 dl.push_back(dataname_dt);
6637 if (dataname_rho.size())
6638 dl.push_back(dataname_rho);
6639 return md.
add_brick(pbr, model::varnamelist(1, varname), dl, tl,
6640 model::mimlist(1, &mim), region);
6653 mutable scalar_type old_alphadt2;
6655 virtual void asm_real_tangent_terms(
const model &md,
size_type ib,
6656 const model::varnamelist &vl,
6657 const model::varnamelist &dl,
6658 const model::mimlist &mims,
6659 model::real_matlist &matl,
6660 model::real_veclist &vecl,
6661 model::real_veclist &,
6663 build_version version)
const {
6664 GMM_ASSERT1(matl.size() == 1,
6665 "Basic d2/dt2 brick has one and only one term");
6666 GMM_ASSERT1(mims.size() == 1,
6667 "Basic d2/dt2 brick need one and only one mesh_im");
6668 GMM_ASSERT1(vl.size() == 1 && dl.size() >= 4 && dl.size() <= 5,
6669 "Wrong number of variables for basic d2/dt2 brick");
6671 bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0);
6673 recompute_matrix = recompute_matrix || md.is_var_newer_than_brick(dl[2], ib);
6674 if (dl.size() > 4) recompute_matrix || md.is_var_newer_than_brick(dl[4], ib);
6676 const model_real_plain_vector &dt = md.
real_variable(dl[2]);
6677 GMM_ASSERT1(gmm::vect_size(dt) == 1,
"Bad format for time step");
6678 const model_real_plain_vector &alpha = md.
real_variable(dl[3]);
6679 GMM_ASSERT1(gmm::vect_size(dt) == 1,
"Bad format for parameter alpha");
6680 scalar_type alphadt2 = gmm::sqr(dt[0]) * alpha[0];
6682 if (!recompute_matrix && alphadt2 != old_alphadt2)
6683 gmm::scale(matl[0], old_alphadt2/alphadt2);
6684 old_alphadt2 = alphadt2;
6686 if (recompute_matrix) {
6689 const mesh_im &mim = *mims[0];
6691 m.intersect_with_mpi_region(rg);
6694 const model_real_plain_vector *rho = 0;
6696 if (dl.size() > 4) {
6701 GMM_ASSERT1(sl == 1,
"Bad format for density");
6704 GMM_TRACE2(
"Mass matrix assembly for d2_on_dt2 brick");
6705 if (dl.size() > 4 && mf_rho) {
6706 gmm::clear(matl[0]);
6708 gmm::scale(matl[0], scalar_type(1) / alphadt2);
6710 gmm::clear(matl[0]);
6712 if (dl.size() > 4) gmm::scale(matl[0], (*rho)[0] / alphadt2);
6713 else gmm::scale(matl[0], scalar_type(1) / alphadt2);
6717 gmm::mult_add(matl[0], gmm::scaled(md.
real_variable(dl[1], 1), dt[0]),
6721 virtual void asm_complex_tangent_terms(
const model &md,
size_type ib,
6722 const model::varnamelist &vl,
6723 const model::varnamelist &dl,
6724 const model::mimlist &mims,
6725 model::complex_matlist &matl,
6726 model::complex_veclist &vecl,
6727 model::complex_veclist &,
6729 build_version version)
const {
6730 GMM_ASSERT1(matl.size() == 1,
6731 "Basic d2/dt2 brick has one and only one term");
6732 GMM_ASSERT1(mims.size() == 1,
6733 "Basic d2/dt2 brick need one and only one mesh_im");
6734 GMM_ASSERT1(vl.size() == 1 && dl.size() >= 4 && dl.size() <= 5,
6735 "Wrong number of variables for basic d2/dt2 brick");
6737 bool recompute_matrix = !((version & model::BUILD_ON_DATA_CHANGE) != 0);
6739 recompute_matrix = recompute_matrix || md.is_var_newer_than_brick(dl[2], ib);
6740 if (dl.size() > 4) recompute_matrix || md.is_var_newer_than_brick(dl[4], ib);
6744 GMM_ASSERT1(gmm::vect_size(dt) == 1,
"Bad format for time step");
6746 GMM_ASSERT1(gmm::vect_size(dt) == 1,
"Bad format for parameter alpha");
6747 scalar_type alphadt2 = gmm::real(gmm::sqr(dt[0]) * alpha[0]);
6749 if (!recompute_matrix && alphadt2 != old_alphadt2)
6750 gmm::scale(matl[0], old_alphadt2/alphadt2);
6751 old_alphadt2 = alphadt2;
6753 if (recompute_matrix) {
6756 const mesh_im &mim = *mims[0];
6758 m.intersect_with_mpi_region(rg);
6761 const model_complex_plain_vector *rho = 0;
6763 if (dl.size() > 4) {
6768 GMM_ASSERT1(sl == 1,
"Bad format for density");
6771 GMM_TRACE2(
"Mass matrix assembly for d2_on_dt2 brick");
6772 if (dl.size() > 4 && mf_rho) {
6773 gmm::clear(matl[0]);
6775 gmm::scale(matl[0], scalar_type(1) / alphadt2);
6777 gmm::clear(matl[0]);
6779 if (dl.size() > 4) gmm::scale(matl[0], (*rho)[0] / alphadt2);
6780 else gmm::scale(matl[0], scalar_type(1) / alphadt2);
6788 virtual std::string declare_volume_assembly_string
6790 const model::varnamelist &)
const {
6791 return std::string();
6794 basic_d2_on_dt2_brick() {
6795 set_flags(
"Basic d2/dt2 brick",
true ,
6805 const std::string &datanameV,
6806 const std::string &dataname_dt,
6807 const std::string &dataname_alpha,
6808 const std::string &dataname_rho,
6810 pbrick pbr = std::make_shared<basic_d2_on_dt2_brick>();
6812 tl.push_back(model::term_description(varnameU, varnameU,
true));
6813 model::varnamelist dl(1, varnameU);
6814 dl.push_back(datanameV);
6815 dl.push_back(dataname_dt);
6816 dl.push_back(dataname_alpha);
6817 if (dataname_rho.size())
6818 dl.push_back(dataname_rho);
6819 return md.
add_brick(pbr, model::varnamelist(1, varnameU), dl, tl,
6820 model::mimlist(1, &mim), region);
6839 void theta_method_dispatcher::set_dispatch_coeff(
const model &md,
size_type ib)
const {
6846 md.matrix_coeff_of_brick(ib) = theta;
6848 md.rhs_coeffs_of_brick(ib)[0] = theta;
6850 md.rhs_coeffs_of_brick(ib)[1] = (scalar_type(1) - theta);
6854 void theta_method_dispatcher::next_real_iter
6856 const model::varnamelist &dl, model::real_matlist &matl,
6857 std::vector<model::real_veclist> &vectl,
6858 std::vector<model::real_veclist> &vectl_sym,
bool first_iter)
const {
6859 next_iter(md, ib, vl, dl, matl, vectl, vectl_sym, first_iter);
6862 void theta_method_dispatcher::next_complex_iter
6864 const model::varnamelist &dl,
6865 model::complex_matlist &matl,
6866 std::vector<model::complex_veclist> &vectl,
6867 std::vector<model::complex_veclist> &vectl_sym,
6868 bool first_iter)
const {
6869 next_iter(md, ib, vl, dl, matl, vectl, vectl_sym, first_iter);
6872 void theta_method_dispatcher::asm_real_tangent_terms
6874 std::vector<model::real_veclist> &,
6875 std::vector<model::real_veclist> &,
6876 build_version version)
const 6877 { md.brick_call(ib, version, 0); }
6879 void theta_method_dispatcher::asm_complex_tangent_terms
6881 std::vector<model::complex_veclist> &,
6882 std::vector<model::complex_veclist> &,
6883 build_version version)
const 6884 { md.brick_call(ib, version, 0); }
6886 theta_method_dispatcher::theta_method_dispatcher(
const std::string &THETA)
6888 param_names.push_back(THETA);
6892 (
model &md, dal::bit_vector ibricks,
const std::string &THETA) {
6893 pdispatcher pdispatch = std::make_shared<theta_method_dispatcher>(THETA);
6894 for (dal::bv_visitor i(ibricks); !i.finished(); ++i)
6899 (
model &md,
const std::string &U,
const std::string &V,
6900 const std::string &pdt,
const std::string &ptheta) {
6906 GMM_ASSERT1(gmm::vect_size(dt) == 1,
"Bad format for time step");
6908 GMM_ASSERT1(gmm::vect_size(dt) == 1,
"Bad format for parameter theta");
6911 scalar_type(1) - scalar_type(1) / theta[0]),
6914 scalar_type(1) / (theta[0]*dt[0])),
6917 -scalar_type(1) / (theta[0]*dt[0])),
6921 GMM_ASSERT1(gmm::vect_size(dt) == 1,
"Bad format for time step");
6922 const model_real_plain_vector &theta = md.
real_variable(ptheta);
6923 GMM_ASSERT1(gmm::vect_size(dt) == 1,
"Bad format for parameter theta");
6926 scalar_type(1) - scalar_type(1) / theta[0]),
6929 scalar_type(1) / (theta[0]*dt[0])),
6932 -scalar_type(1) / (theta[0]*dt[0])),
6945 const std::string &pdt,
const std::string &ptwobeta,
6946 const std::string &pgamma) {
6956 if (twobeta != gamma) {
6958 md.set_dispatch_coeff();
6962 md.
assembly(model::BUILD_COMPLETE_RHS);
6965 model_complex_plain_vector W(nbdof), RHS(nbdof);
6966 gmm::copy(gmm::sub_vector(md.
complex_rhs(), md.interval_of_variable(U)),
6971 gmm::cg(md.linear_complex_matrix_term(id2dt2b, 0),
6972 W, RHS, gmm::identity_matrix(), iter);
6973 GMM_ASSERT1(iter.converged(),
"Velocity not well computed");
6975 gmm::scaled(W, complex_type(1)/(twobeta*dt)),
6979 if (twobeta != gamma) {
6981 md.set_dispatch_coeff();
6985 GMM_ASSERT1(
false,
"to be done");
6994 if (twobeta != gamma) {
6996 md.set_dispatch_coeff();
7000 md.
assembly(model::BUILD_COMPLETE_RHS);
7003 model_real_plain_vector W(nbdof), RHS(nbdof);
7004 gmm::copy(gmm::sub_vector(md.
real_rhs(), md.interval_of_variable(U)),
7009 gmm::cg(md.linear_real_matrix_term(id2dt2b, 0),
7010 W, RHS, gmm::identity_matrix(), iter);
7011 GMM_ASSERT1(iter.converged(),
"Velocity not well computed");
7013 gmm::scaled(W, scalar_type(1)/(twobeta*dt)),
7017 if (twobeta != gamma) {
7019 md.set_dispatch_coeff();
7036 gmm::uint64_type id_num;
7040 typedef model::build_version build_version;
7043 md.matrix_coeff_of_brick(ib) = scalar_type(1)/scalar_type(2);
7044 md.rhs_coeffs_of_brick(ib)[0] = scalar_type(1);
7045 md.rhs_coeffs_of_brick(ib)[1] = scalar_type(1)/scalar_type(2);
7048 template <
typename MATLIST,
typename VECTLIST>
7050 const model::varnamelist &vl,
7051 const model::varnamelist &dl,
7053 VECTLIST &vectl, VECTLIST &vectl_sym,
7054 bool first_iter)
const {
7056 pbrick pbr = md.brick_pointer(ib);
7060 if (!(pbr->is_linear()))
7061 md.add_temporaries(vl, id_num);
7062 md.add_temporaries(dl, id_num);
7063 for (
auto &&v : vectl[1]) gmm::clear(v);
7064 for (
auto &&v : vectl_sym[1]) gmm::clear(v);
7067 if (pbr->is_linear()) {
7070 if (first_iter) md.update_brick(ib, model::BUILD_RHS);
7071 for (
auto &&v : vectl[1]) gmm::clear(v);
7072 for (
auto &&v : vectl_sym[1]) gmm::clear(v);
7073 md.linear_brick_add_to_rhs(ib, 1, 0);
7079 const model::varnamelist &dl, model::real_matlist &matl,
7080 std::vector<model::real_veclist> &vectl,
7081 std::vector<model::real_veclist> &vectl_sym,
bool first_iter)
const {
7082 next_iter(md, ib, vl, dl, matl, vectl, vectl_sym, first_iter);
7085 void next_complex_iter
7087 const model::varnamelist &dl,
7088 model::complex_matlist &matl,
7089 std::vector<model::complex_veclist> &vectl,
7090 std::vector<model::complex_veclist> &vectl_sym,
7091 bool first_iter)
const {
7092 next_iter(md, ib, vl, dl, matl, vectl, vectl_sym, first_iter);
7095 void asm_real_tangent_terms
7097 std::vector<model::real_veclist> &vectl,
7098 std::vector<model::real_veclist> &vectl_sym,
7099 build_version version)
const {
7101 scalar_type half = scalar_type(1)/scalar_type(2);
7102 pbrick pbr = md.brick_pointer(ib);
7105 const model::varnamelist &vl = md.varnamelist_of_brick(ib);
7106 const model::varnamelist &dl = md.datanamelist_of_brick(ib);
7108 if (!(pbr->is_linear())) {
7109 for (
size_type i = 0; i < vl.size(); ++i) {
7110 bool is_uptodate = md.temporary_uptodate(vl[i], id_num, ind);
7111 if (!is_uptodate && ind !=
size_type(-1))
7115 md.set_default_iter_of_variable(vl[i], ind);
7120 for (
size_type i = 0; i < dl.size(); ++i) {
7121 bool is_uptodate = md.temporary_uptodate(dl[i], id_num, ind);
7122 if (!is_uptodate && ind !=
size_type(-1)) {
7127 md.set_default_iter_of_variable(dl[i], ind);
7131 md.brick_call(ib, version, 0);
7132 if (pbr->is_linear()) {
7134 for (
auto &&v : vectl[1]) gmm::clear(v);
7135 for (
auto &&v : vectl_sym[1]) gmm::clear(v);
7136 md.linear_brick_add_to_rhs(ib, 1, 1);
7139 md.reset_default_iter_of_variables(dl);
7140 if (!(pbr->is_linear()))
7141 md.reset_default_iter_of_variables(vl);
7144 virtual void asm_complex_tangent_terms
7146 std::vector<model::complex_veclist> &vectl,
7147 std::vector<model::complex_veclist> &vectl_sym,
7148 build_version version)
const {
7150 scalar_type half = scalar_type(1)/scalar_type(2);
7151 pbrick pbr = md.brick_pointer(ib);
7154 const model::varnamelist &vl = md.varnamelist_of_brick(ib);
7155 const model::varnamelist &dl = md.datanamelist_of_brick(ib);
7157 if (!(pbr->is_linear())) {
7158 for (
size_type i = 0; i < vl.size(); ++i) {
7159 bool is_uptodate = md.temporary_uptodate(vl[i], id_num, ind);
7160 if (!is_uptodate && ind !=
size_type(-1))
7164 md.set_default_iter_of_variable(vl[i], ind);
7169 for (
size_type i = 0; i < dl.size(); ++i) {
7170 bool is_uptodate = md.temporary_uptodate(dl[i], id_num, ind);
7171 if (!is_uptodate && ind !=
size_type(-1)) {
7176 md.set_default_iter_of_variable(dl[i], ind);
7180 md.brick_call(ib, version, 0);
7181 if (pbr->is_linear()) {
7183 for (
auto &&v : vectl[1]) gmm::clear(v);
7184 for (
auto &&v : vectl_sym[1]) gmm::clear(v);
7185 md.linear_brick_add_to_rhs(ib, 1, 1);
7188 md.reset_default_iter_of_variables(dl);
7189 if (!(pbr->is_linear()))
7190 md.reset_default_iter_of_variables(vl);
7194 { id_num = act_counter(); }
7199 pdispatcher pdispatch = std::make_shared<midpoint_dispatcher>();
7200 for (dal::bv_visitor i(ibricks); !i.finished(); ++i)
multi-threaded distribution of a single vector or a matrix.
const model_real_plain_vector & real_rhs() const
Gives the access to the right hand side of the tangent linear system.
void add_fixed_size_data(const std::string &name, size_type size, size_type niter=1)
Add a fixed size data to the model.
const APIDECL std::string & mult_varname_Dirichlet(model &md, size_type ind_brick)
When ind_brick is the index of a Dirichlet brick with multiplier on the model md, the function return...
virtual size_type nb_dof() const
Return the total number of degrees of freedom.
structure used to hold a set of convexes and/or convex faces.
void asm_stiffness_matrix_for_homogeneous_scalar_elliptic_componentwise(MAT &M, const mesh_im &mim, const mesh_fem &mf, const VECT &A, const mesh_region &rg=mesh_region::all_convexes())
The same but with a constant matrix.
const model_complex_plain_vector & complex_rhs() const
Gives access to the right hand side of the tangent linear system.
size_type nb_dof() const
Total number of degrees of freedom in the model.
size_type APIDECL add_normal_Dirichlet_condition_with_multipliers(model &md, const mesh_im &mim, const std::string &varname, const std::string &multname, size_type region, const std::string &dataname=std::string())
Add a Dirichlet condition to the normal component of the vector (or tensor) valued variable varname a...
size_type APIDECL add_generalized_Dirichlet_condition_with_Nitsche_method(model &md, const mesh_im &mim, const std::string &varname, const std::string &Neumannterm, const std::string &datagamma0, size_type region, scalar_type theta, const std::string &datag, const std::string &dataH)
Add a Dirichlet condition on the variable varname and the mesh region region.
void asm_stiffness_matrix_for_scalar_elliptic(MAT &M, const mesh_im &mim, const mesh_fem &mf, const mesh_fem &mf_data, const VECT &A, const mesh_region &rg=mesh_region::all_convexes())
assembly of , where is a (symmetric positive definite) NxN matrix.
void asm_stokes_B(const MAT &B, const mesh_im &mim, const mesh_fem &mf_u, const mesh_fem &mf_p, const mesh_region &rg=mesh_region::all_convexes())
Build the mixed pressure term .
void change_mims_of_brick(size_type ib, const mimlist &ml)
Change the mim list of a brick.
const auto PREFIX_OLD
A prefix to refer to the previous version of a variable.
void disable_brick(size_type ib)
Disable a brick.
void APIDECL add_midpoint_dispatcher(model &md, dal::bit_vector ibricks)
Add a midpoint time dispatcher to a list of bricks.
size_type APIDECL add_normal_Dirichlet_condition_with_Nitsche_method(model &md, const mesh_im &mim, const std::string &varname, const std::string &Neumannterm, const std::string &datagamma0, size_type region, scalar_type theta=scalar_type(0), const std::string &datag=std::string())
Add a Dirichlet condition on the normal component of the variable varname and the mesh region region...
void disable_variable(const std::string &name)
Disable a variable (and its attached mutlipliers).
size_type APIDECL add_pointwise_constraints_with_given_multipliers(model &md, const std::string &varname, const std::string &multname, const std::string &dataname_pt, const std::string &dataname_unitv=std::string(), const std::string &dataname_val=std::string())
Add some pointwise constraints on the variable varname using a given multiplier multname.
void add_macro(const std::string &name, const std::string &expr)
Add a macro definition for the high generic assembly langage.
void check_brick_stiffness_rhs(size_type ind_brick) const
check consistency of RHS and Stiffness matrix for brick with
size_type APIDECL add_isotropic_linearized_elasticity_brick_pstress(model &md, const mesh_im &mim, const std::string &varname, const std::string &data_E, const std::string &data_nu, size_type region)
Linear elasticity brick ( ).
void listvar(std::ostream &ost) const
List the model variables and constant.
void change_variables_of_brick(size_type ib, const varnamelist &vl)
Change the variable list of a brick.
The Iteration object calculates whether the solution has reached the desired accuracy, or whether the maximum number of iterations has been reached.
void asm_homogeneous_Helmholtz(MAT &M, const mesh_im &mim, const mesh_fem &mf_u, const VECT &K_squared, const mesh_region &rg=mesh_region::all_convexes())
assembly of the term , for the helmholtz equation ( , with ).
void asm_stiffness_matrix_for_laplacian_componentwise(MAT &M, const mesh_im &mim, const mesh_fem &mf, const mesh_fem &mf_data, const VECT &A, const mesh_region &rg=mesh_region::all_convexes())
The same as getfem::asm_stiffness_matrix_for_laplacian , but on each component of mf when mf has a qd...
void listbricks(std::ostream &ost, size_type base_id=0) const
List the model bricks.
void asm_mass_matrix(const MAT &M, const mesh_im &mim, const mesh_fem &mf1, const mesh_region &rg=mesh_region::all_convexes())
generic mass matrix assembly (on the whole mesh or on the specified convex set or boundary) ...
void asm_stiffness_matrix_for_homogeneous_laplacian_componentwise(const MAT &M, const mesh_im &mim, const mesh_fem &mf, const mesh_region &rg=mesh_region::all_convexes())
assembly of .
const std::string & varname_of_brick(size_type ind_brick, size_type ind_var)
Gives the name of the variable of index ind_var of the brick of index ind_brick.
size_type APIDECL add_source_term_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr, size_type region=size_type(-1), const std::string &directdataname=std::string())
Add a source term on the variable varname.
size_type APIDECL add_isotropic_linearized_elasticity_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataname_lambda, const std::string &dataname_mu, size_type region=size_type(-1), const std::string &dataname_preconstraint=std::string())
Linear elasticity brick ( ).
size_type APIDECL add_mass_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr_rho=std::string(), size_type region=size_type(-1))
Mass brick ( ).
void interpolation(const mesh_fem &mf_source, const mesh_fem &mf_target, const VECTU &U, VECTV &V, int extrapolation=0, double EPS=1E-10, mesh_region rg_source=mesh_region::all_convexes(), mesh_region rg_target=mesh_region::all_convexes())
interpolation/extrapolation of (mf_source, U) on mf_target.
void asm_stiffness_matrix_for_homogeneous_vector_elliptic(MAT &M, const mesh_im &mim, const mesh_fem &mf, const VECT &A, const mesh_region &rg=mesh_region::all_convexes())
Assembly of , where is a NxNxQxQ (symmetric positive definite) constant tensor.
int region_is_faces_of(const getfem::mesh &m1, const mesh_region &rg2, const getfem::mesh &m2) const
Test if the region is a boundary of a list of faces of elements of region rg.
size_type APIDECL add_Helmholtz_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr, size_type region=size_type(-1))
Add a Helmoltz brick to the model.
computation of the condition number of dense matrices.
Describe a mesh (collection of convexes (elements) and points).
pinterpolate_transformation interpolate_transformation_neighbour_instance()
Create a new instance of a transformation corresponding to the interpolation on the neighbour element...
void asm_source_term(const VECT1 &B, const mesh_im &mim, const mesh_fem &mf, const mesh_fem &mf_data, const VECT2 &F, const mesh_region &rg=mesh_region::all_convexes())
source term (for both volumic sources and boundary (Neumann) sources).
void enable_variable(const std::string &name)
Enable a variable (and its attached mutlipliers).
void APIDECL velocity_update_for_Newmark_scheme(model &md, size_type id2dt2b, const std::string &U, const std::string &V, const std::string &pdt, const std::string &ptwobeta, const std::string &pgamma)
Function which udpate the velocity $v^{n+1}$ after the computation of the displacement $u^{n+1}$ and ...
bool is_old(const std::string &name)
Does the variable have Old_ prefix.
Describe an integration method linked to a mesh.
void add_affine_dependent_variable(const std::string &name, const std::string &org_name, scalar_type alpha=scalar_type(1))
Add a "virtual" variable be an affine depedent variable with respect to another variable.
size_type APIDECL add_pointwise_constraints_with_penalization(model &md, const std::string &varname, scalar_type penalisation_coeff, const std::string &dataname_pt, const std::string &dataname_unitv=std::string(), const std::string &dataname_val=std::string())
Add some pointwise constraints on the variable varname thanks to a penalization.
virtual void next_iter()
For transient problems.
void asm_stiffness_matrix_for_homogeneous_scalar_elliptic(MAT &M, const mesh_im &mim, const mesh_fem &mf, const VECT &A, const mesh_region &rg=mesh_region::all_convexes())
The same but with a constant matrix.
void asm_stiffness_matrix_for_homogeneous_laplacian(const MAT &M, const mesh_im &mim, const mesh_fem &mf, const mesh_region &rg=mesh_region::all_convexes())
assembly of .
The time integration scheme object provides the necessary methods for the model object to apply a tim...
size_type APIDECL add_linear_incompressibility(model &md, const mesh_im &mim, const std::string &varname, const std::string &multname_pressure, size_type region=size_type(-1), const std::string &dataexpr_penal_coeff=std::string())
Mixed linear incompressibility condition brick.
takes a list (more often it's a std::vector) of matrices or vectors, creates an empty copy on each th...
const mesh_fem & mesh_fem_of_variable(const std::string &name) const
Gives the access to the mesh_fem of a variable if any.
``Model'' variables store the variables, the data and the description of a model. ...
void change_terms_of_brick(size_type ib, const termlist &terms)
Change the term list of a brick.
size_type APIDECL add_Dirichlet_condition_with_Nitsche_method(model &md, const mesh_im &mim, const std::string &varname, const std::string &Neumannterm, const std::string &datagamma0, size_type region, scalar_type theta=scalar_type(0), const std::string &datag=std::string())
Add a Dirichlet condition on the variable varname and the mesh region region.
void asm_homogeneous_source_term(const VECT1 &B, const mesh_im &mim, const mesh_fem &mf, const VECT2 &F, const mesh_region &rg=mesh_region::all_convexes())
source term (for both volumic sources and boundary (Neumann) sources).
size_t size_type
used as the common size type in the library
void change_update_flag_of_brick(size_type ib, bool flag)
Change the update flag of a brick.
void add_initialized_matrix_data(const std::string &name, const base_matrix &M)
Add a fixed size data (assumed to be a matrix) to the model and initialized with M.
Model representation in Getfem.
void asm_stiffness_matrix_for_scalar_elliptic_componentwise(MAT &M, const mesh_im &mim, const mesh_fem &mf, const mesh_fem &mf_data, const VECT &A, const mesh_region &rg=mesh_region::all_convexes())
The same but on each component of mf when mf has a qdim > 1.
size_type add_brick(pbrick pbr, const varnamelist &varnames, const varnamelist &datanames, const termlist &terms, const mimlist &mims, size_type region)
Add a brick to the model.
Interpolation of fields from a mesh_fem onto another.
virtual dim_type get_qdim() const
Return the Q dimension.
size_type APIDECL add_isotropic_linearized_elasticity_brick_pstrain(model &md, const mesh_im &mim, const std::string &varname, const std::string &data_E, const std::string &data_nu, size_type region)
Linear elasticity brick ( ).
void add_multiplier(const std::string &name, const mesh_fem &mf, const std::string &primal_name, size_type niter=1)
Add a particular variable linked to a fem being a multiplier with respect to a primal variable...
this is the above solutions for linux, but it still needs to be tested.
bool is_complex() const
Boolean which says if the model deals with real or complex unknowns and data.
The time dispatcher object modify the result of a brick in order to apply a time integration scheme...
size_type APIDECL add_Dirichlet_condition_with_simplification(model &md, const std::string &varname, size_type region, const std::string &dataname=std::string())
Add a (simple) Dirichlet condition on the variable varname and the mesh region region.
"iterator" class for regions.
size_type APIDECL add_generalized_Dirichlet_condition_with_multipliers(model &md, const mesh_im &mim, const std::string &varname, const std::string &multname, size_type region, const std::string &dataname, const std::string &Hname)
Add a generalized Dirichlet condition on the variable varname and the mesh region region...
void del_macro(const std::string &name)
Delete a previously defined macro definition.
void delete_variable(const std::string &varname)
Delete a variable or data of the model.
bool is_data(const std::string &name) const
Says if a name corresponds to a declared data or disabled variable.
std::string Neumann_term(const std::string &varname, size_type region)
Gives the assembly string corresponding to the Neumann term of the fem variable varname on region...
A langage for generic assembly of pde boundary value problems.
virtual void first_iter()
For transient problems.
void add_filtered_fem_variable(const std::string &name, const mesh_fem &mf, size_type region, size_type niter=1)
Add a variable linked to a fem with the dof filtered with respect to a mesh region.
GEneric Tool for Finite Element Methods.
size_type APIDECL add_basic_d2_on_dt2_brick(model &md, const mesh_im &mim, const std::string &varnameU, const std::string &datanameV, const std::string &dataname_dt, const std::string &dataname_alpha, const std::string &dataname_rho=std::string(), size_type region=size_type(-1))
Basic d2/dt2 brick ( ).
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Describe a finite element method linked to a mesh.
size_type APIDECL add_Laplacian_brick(model &md, const mesh_im &mim, const std::string &varname, size_type region=size_type(-1))
Add a Laplacian term on the variable varname (in fact with a minus : :math:-\text{div}(\nabla u))...
size_type nb_filtered_index() const
Total numbers of filtered index (integration points)
model_real_plain_vector & set_real_variable(const std::string &name, size_type niter) const
Gives the write access to the vector value of a variable.
Conjugate gradient iterative solver.
void APIDECL add_theta_method_dispatcher(model &md, dal::bit_vector ibricks, const std::string &THETA)
Add a theta-method time dispatcher to a list of bricks.
size_type APIDECL add_normal_Dirichlet_condition_with_penalization(model &md, const mesh_im &mim, const std::string &varname, scalar_type penalization_coeff, size_type region, const std::string &dataname=std::string(), const mesh_fem *mf_mult=0)
Add a Dirichlet condition to the normal component of the vector (or tensor) valued variable varname a...
void APIDECL velocity_update_for_order_two_theta_method(model &md, const std::string &U, const std::string &V, const std::string &pdt, const std::string &ptheta)
Function which udpate the velocity $v^{n+1}$ after the computation of the displacement $u^{n+1}$ and ...
The virtual brick has to be derived to describe real model bricks.
void asm_normal_source_term(VECT1 &B, const mesh_im &mim, const mesh_fem &mf, const mesh_fem &mf_data, const VECT2 &F, const mesh_region &rg)
Normal source term (for boundary (Neumann) condition).
void asm_homogeneous_normal_source_term(VECT1 &B, const mesh_im &mim, const mesh_fem &mf, const VECT2 &F, const mesh_region &rg)
Homogeneous normal source term (for boundary (Neumann) condition).
void APIDECL compute_isotropic_linearized_Von_Mises_pstrain(model &md, const std::string &varname, const std::string &data_E, const std::string &data_nu, const mesh_fem &mf_vm, model_real_plain_vector &VM)
Compute the Von-Mises stress of a displacement field for isotropic linearized elasticity in 3D or in ...
Extract a basis of the range of a (large sparse) matrix from the columns of this matrix.
void resize_fixed_size_variable(const std::string &name, size_type size)
Resize a fixed size variable (or data) of the model.
size_type APIDECL add_generalized_Dirichlet_condition_with_penalization(model &md, const mesh_im &mim, const std::string &varname, scalar_type penalization_coeff, size_type region, const std::string &dataname, const std::string &Hname, const mesh_fem *mf_mult=0)
Add a Dirichlet condition on the variable varname and the mesh region region.
size_type APIDECL add_pointwise_constraints_with_multipliers(model &md, const std::string &varname, const std::string &dataname_pt, const std::string &dataname_unitv=std::string(), const std::string &dataname_val=std::string())
Add some pointwise constraints on the variable varname using multiplier.
void run(Function f, Parameters...params)
Run function f in parallel part to capture it's exceptions.
void add_mim_to_brick(size_type ib, const mesh_im &mim)
Add an integration method to a brick.
void touch_brick(size_type ib)
Force the re-computation of a brick for the next assembly.
bool variable_exists(const std::string &name) const
Says if a name corresponds to a declared variable.
void add_fem_data(const std::string &name, const mesh_fem &mf, dim_type qdim=1, size_type niter=1)
Add a data being the dofs of a finite element method to the model.
void asm_stiffness_matrix_for_vector_elliptic(MAT &M, const mesh_im &mim, const mesh_fem &mf, const mesh_fem &mf_data, const VECT &A, const mesh_region &rg=mesh_region::all_convexes())
Assembly of , where is a NxNxQxQ (symmetric positive definite) tensor defined on mf_data...
void enable_brick(size_type ib)
Enable a brick.
size_type APIDECL add_normal_source_term_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr, size_type region)
Add a source term on the variable varname on a boundary region.
size_type APIDECL add_basic_d_on_dt_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataname_dt, const std::string &dataname_rho=std::string(), size_type region=size_type(-1))
Basic d/dt brick ( ).
void add_im_data(const std::string &name, const im_data &im_data, size_type niter=1)
Add data, defined at integration points.
size_type APIDECL add_source_term(model &md, const mesh_im &mim, const std::string &expr, size_type region=size_type(-1), std::string brickname="", std::string directvarname=std::string(), const std::string &directdataname=std::string(), bool return_if_nonlin=false)
Add a source term given by the assembly string expr which will be assembled in region region and with...
std::string new_name(const std::string &name)
Gives a non already existing variable name begining by name.
void asm_stiffness_matrix_for_laplacian(MAT &M, const mesh_im &mim, const mesh_fem &mf, const mesh_fem &mf_data, const VECT &A, const mesh_region &rg=mesh_region::all_convexes())
assembly of , where is scalar.
void add_fem_variable(const std::string &name, const mesh_fem &mf, size_type niter=1)
Add a variable being the dofs of a finite element method to the model.
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
const mesh & linked_mesh() const
Give a reference to the linked mesh of type mesh.
Allows to re-throw exceptions, generated in OpemMP parallel section.
const mesh_fem * pmesh_fem_of_variable(const std::string &name) const
Gives a pointer to the mesh_fem of a variable if any.
const model_real_plain_vector & real_variable(const std::string &name, size_type niter) const
Gives the access to the vector value of a variable.
void APIDECL compute_isotropic_linearized_Von_Mises_pstress(model &md, const std::string &varname, const std::string &data_E, const std::string &data_nu, const mesh_fem &mf_vm, model_real_plain_vector &VM)
Compute the Von-Mises stress of a displacement field for isotropic linearized elasticity in 3D or in ...
bool is_true_data(const std::string &name) const
Says if a name corresponds to a declared data.
size_type APIDECL add_linear_term(model &md, const mesh_im &mim, const std::string &expr, size_type region=size_type(-1), bool is_sym=false, bool is_coercive=false, std::string brickname="", bool return_if_nonlin=false)
Add a matrix term given by the assembly string expr which will be assembled in region region and with...
model_complex_plain_vector & set_complex_variable(const std::string &name, size_type niter) const
Gives the write access to the vector value of a variable.
void delete_brick(size_type ib)
Delete the brick of index ib from the model.
std::string no_old_prefix_name(const std::string &name)
Strip the variable name from prefix Old_ if it has one.
void asm_Helmholtz(MAT &M, const mesh_im &mim, const mesh_fem &mf_u, const mesh_fem &mf_data, const VECT &K_squared, const mesh_region &rg=mesh_region::all_convexes())
assembly of the term , for the helmholtz equation ( , with ).
im_data provides indexing to the integration points of a mesh im object.
const std::string & dataname_of_brick(size_type ind_brick, size_type ind_data)
Gives the name of the data of index ind_data of the brick of index ind_brick.
const mesh_region region(size_type id) const
Return the region of index 'id'.
void add_time_dispatcher(size_type ibrick, pdispatcher pdispatch)
Add a time dispacther to a brick.
size_type APIDECL add_nonlinear_term(model &md, const mesh_im &mim, const std::string &expr, size_type region=size_type(-1), bool is_sym=false, bool is_coercive=false, std::string brickname="")
Add a nonlinear term given by the assembly string expr which will be assembled in region region and w...
size_type APIDECL add_Fourier_Robin_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr, size_type region)
Add a Fourier-Robin brick to the model.
size_type APIDECL add_Dirichlet_condition_with_penalization(model &md, const mesh_im &mim, const std::string &varname, scalar_type penalization_coeff, size_type region, const std::string &dataname=std::string(), const mesh_fem *mf_mult=0)
Add a Dirichlet condition on the variable varname and the mesh region region.
void add_initialized_tensor_data(const std::string &name, const base_tensor &t)
Add a fixed size data (assumed to be a tensor) to the model and initialized with t.
void interpolation_von_mises_or_tresca(const getfem::mesh_fem &mf_u, const getfem::mesh_fem &mf_vm, const VEC1 &U, VEC2 &VM, const getfem::mesh_fem &mf_lambda, const VEC3 &lambda, const getfem::mesh_fem &mf_mu, const VEC3 &mu, bool tresca)
Compute the Von-Mises stress of a field (valid for linearized elasticity in 2D and 3D) ...
Compute the gradient of a field on a getfem::mesh_fem.
Miscelleanous assembly routines for common terms. Use the low-level generic assembly. Prefer the high-level one.
void add_fixed_size_variable(const std::string &name, size_type size, size_type niter=1)
Add a fixed size variable to the model assumed to be a vector.
void check_stiffness_matrix_and_rhs(const model &, size_type, const model::termlist &tlist, const model::varnamelist &, const model::varnamelist &, const model::mimlist &, model::real_matlist &, model::real_veclist &, model::real_veclist &, size_type rg, const scalar_type delta=1e-8) const
check consistency of stiffness matrix and rhs
std::shared_ptr< const virtual_brick > pbrick
type of pointer on a brick
size_type nb_tensor_elem() const
sum of tensor elements, M(3,3) will have 3*3=9 elements
size_type APIDECL add_generic_elliptic_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr, size_type region=size_type(-1))
Add an elliptic term on the variable varname.
const mesh_fem & classical_mesh_fem(const mesh &mesh, dim_type degree, dim_type qdim=1, bool complete=false)
Gives the descriptor of a classical finite element method of degree K on mesh.
void asm_mass_matrix_param(const MAT &M, const mesh_im &mim, const mesh_fem &mf1, const mesh_fem &mf2, const mesh_fem &mf_data, const VECT &A, const mesh_region &rg=mesh_region::all_convexes())
generic mass matrix assembly with an additional parameter (on the whole mesh or on the specified boun...
void asm_qu_term(MAT &M, const mesh_im &mim, const mesh_fem &mf_u, const mesh_fem &mf_d, const VECT &Q, const mesh_region &rg)
assembly of
size_type APIDECL add_Dirichlet_condition_with_multipliers(model &md, const mesh_im &mim, const std::string &varname, const std::string &multname, size_type region, const std::string &dataname=std::string())
Add a Dirichlet condition on the variable varname and the mesh region region.
const model_complex_plain_vector & complex_variable(const std::string &name, size_type niter) const
Gives the access to the vector value of a variable.
void change_data_of_brick(size_type ib, const varnamelist &vl)
Change the data list of a brick.
virtual void assembly(build_version version)
Assembly of the tangent system taking into account the terms from all bricks.
void APIDECL change_penalization_coeff(model &md, size_type ind_brick, scalar_type penalisation_coeff)
Change the penalization coefficient of a Dirichlet condition with penalization brick.