26 void fem_sum::init() {
27 cvr = pfems[0]->ref_convex(cv);
28 dim_ = cvr->structure()->dim();
29 is_equiv = !smart_global_dof_linking_;
30 real_element_defined =
true;
31 is_polycomp = is_pol = is_lag = is_standard_fem =
false;
36 nm <<
"FEM_SUM(" << pfems[0]->debug_name() <<
",";
37 for (
size_type i = 1; i < pfems.size(); ++i)
38 nm << pfems[i]->debug_name() <<
",";
39 nm <<
" cv:" << cv <<
")";
40 debug_name_ = nm.str();
43 for (
size_type i = 0; i < pfems.size(); ++i) {
44 GMM_ASSERT1(pfems[i]->target_dim() == 1,
"Vectorial fems not supported");
46 for (
size_type k = 0; k < pfems[i]->nb_dof(cv); ++k) {
47 add_node(pfems[i]->dof_types()[k], pfems[i]->node_of_dof(cv,k));
53 void fem_sum::mat_trans(base_matrix &M,
61 std::vector<pdof_description> hermdof(dim());
62 for (dim_type
id = 0;
id < dim(); ++id)
66 base_vector val(1), val2(1);
67 base_matrix grad(1, dim());
70 for (
size_type ifem1 = 0, i=0; ifem1 < pfems.size(); ++ifem1) {
71 pfem pf1 = pfems[ifem1];
73 for (
size_type idof1 = 0; idof1 < pf1->nb_dof(cv); ++idof1, ++i) {
74 if (pf1->dof_types()[idof1] == gdof) {
75 base_vector coeff(pfems[ifem1]->nb_dof(cv));
77 fem_interpolation_context fic(pgt, pf1, base_node(dim()), G, cv);
78 for (
size_type ifem2 = 0, j=0; ifem2 < pfems.size(); ++ifem2) {
79 pfem pf2 = pfems[ifem2];
80 fem_interpolation_context fic2(pgt, pf2, base_node(dim()), G, cv);
81 for (
size_type idof2 = 0; idof2 < pf2->nb_dof(cv); ++idof2, ++j) {
85 base_vector coeff2(pfems[ifem2]->nb_dof(cv));
89 fic.set_xref(pf2->node_of_dof(cv, idof2));
90 fic2.set_xref(pf2->node_of_dof(cv, idof2));
91 if (dof_weak_compatibility(pdd, lagdof) == 0) {
92 pfems[ifem1]->interpolation(fic, coeff, val, 1);
94 pfems[ifem2]->interpolation(fic2, coeff2, val2, 1);
96 M(i, j) = -val[0]*val2[0];
104 else for (
size_type id = 0;
id < dim(); ++id) {
105 if (dof_weak_compatibility(pdd, hermdof[
id]) == 0) {
106 pfems[ifem1]->interpolation_grad(fic, coeff, grad, 1);
107 M(i, j) = -grad(0,
id);
108 cout <<
"dof " << idof2 <<
"compatible with hermite "
114 "Sorry, smart_global_dof_linking not "
115 "compatible with this kind of dof");
129 for (
size_type i = 0; i < pfems.size(); ++i) {
131 if (j >= nb) j -= pfems[i]->nb_dof(cv);
132 else return pfems[i]->index_of_global_dof(cv, j);
134 GMM_ASSERT1(
false,
"incoherent global dof.");
137 void fem_sum::base_value(
const base_node &,
139 { GMM_ASSERT1(
false,
"No base values, real only element."); }
140 void fem_sum::grad_base_value(
const base_node &,
142 { GMM_ASSERT1(
false,
"No base values, real only element."); }
143 void fem_sum::hess_base_value(
const base_node &,
145 { GMM_ASSERT1(
false,
"No base values, real only element."); }
147 void fem_sum::real_base_value(
const fem_interpolation_context &c,
150 bgeot::multi_index mi(2);
151 mi[1] = target_dim(); mi[0] =
short_type(nb_dof(0));
153 base_tensor::iterator it = t.begin(), itf;
155 fem_interpolation_context c0 = c;
156 std::vector<base_tensor> val_e(pfems.size());
157 for (
size_type k = 0; k < pfems.size(); ++k) {
159 c0.set_pfp(
fem_precomp(pfems[k], c0.pfp()->get_ppoint_tab(),
161 }
else { c0.set_pf(pfems[k]); }
162 c0.base_value(val_e[k]);
165 for (dim_type q = 0; q < target_dim(); ++q) {
166 for (
size_type k = 0; k < pfems.size(); ++k) {
167 itf = val_e[k].begin() + q * pfems[k]->nb_dof(cv);
168 for (
size_type i = 0; i < pfems[k]->nb_dof(cv); ++i)
172 assert(it == t.end());
173 if (!is_equivalent() && withM) {
175 t.mat_transp_reduction(tt, c.M(), 0);
180 void fem_sum::real_grad_base_value(
const fem_interpolation_context &c,
181 base_tensor &t,
bool withM)
const {
182 bgeot::multi_index mi(3);
183 mi[2] =
short_type(c.N()); mi[1] = target_dim();
186 base_tensor::iterator it = t.begin(), itf;
188 fem_interpolation_context c0 = c;
189 std::vector<base_tensor> grad_e(pfems.size());
190 for (
size_type k = 0; k < pfems.size(); ++k) {
192 c0.set_pfp(
fem_precomp(pfems[k], c0.pfp()->get_ppoint_tab(),
194 }
else { c0.set_pf(pfems[k]); }
195 c0.grad_base_value(grad_e[k]);
198 for (dim_type k = 0; k < c.N() ; ++k) {
199 for (dim_type q = 0; q < target_dim(); ++q) {
200 for (
size_type f = 0; f < pfems.size(); ++f) {
201 itf = grad_e[f].begin()
202 + (k * target_dim() + q) * pfems[f]->nb_dof(cv);
203 for (
size_type i = 0; i < pfems[f]->nb_dof(cv); ++i)
208 assert(it == t.end());
209 if (!is_equivalent() && withM) {
211 t.mat_transp_reduction(tt, c.M(), 0);
215 void fem_sum::real_hess_base_value(
const fem_interpolation_context &c,
216 base_tensor &t,
bool withM)
const {
217 t.adjust_sizes(nb_dof(0), target_dim(), gmm::sqr(c.N()));
218 base_tensor::iterator it = t.begin(), itf;
220 fem_interpolation_context c0 = c;
221 std::vector<base_tensor> hess_e(pfems.size());
222 for (
size_type k = 0; k < pfems.size(); ++k) {
224 c0.set_pfp(
fem_precomp(pfems[k], c0.pfp()->get_ppoint_tab(),
226 }
else { c0.set_pf(pfems[k]); }
227 c0.hess_base_value(hess_e[k]);
230 dim_type NNdim = dim_type(gmm::sqr(c.N())*target_dim());
231 for (dim_type jkq = 0; jkq < NNdim ; ++jkq) {
232 for (
size_type f = 0; f < pfems.size(); ++f) {
233 itf = hess_e[f].begin() + (jkq * pfems[f]->nb_dof(cv));
234 for (
size_type i = 0; i < pfems[f]->nb_dof(cv); ++i)
238 assert(it == t.end());
239 if (!is_equivalent() && withM) {
241 t.mat_transp_reduction(tt, c.M(), 0);
245 void mesh_fem_sum::clear_build_methods() {
246 for (
size_type i = 0; i < build_methods.size(); ++i)
248 build_methods.clear();
250 void mesh_fem_sum::clear() {
252 clear_build_methods();
257 DAL_SIMPLE_KEY(special_mflsum_key,
pfem);
259 void mesh_fem_sum::adapt() {
263 for (
const mesh_fem *pmf : mfs)
264 GMM_ASSERT1(!(pmf->is_reduced()),
265 "Sorry fem_sum for reduced mesh_fem is not implemented");
268 std::vector<pfem> pfems;
269 bool is_cv_dep =
false;
270 for (
const mesh_fem *pmf : mfs) {
271 if (pmf->convex_index().is_in(i)) {
272 pfem pf = pmf->fem_of_element(i);
275 if (pf->is_on_real_element())
280 if (pfems.size() == 1) {
283 else if (pfems.size() > 0) {
284 if (situations.find(pfems) == situations.end() || is_cv_dep) {
285 pfem pf = std::make_shared<fem_sum>(pfems, i,
286 smart_global_dof_linking_);
287 dal::pstatic_stored_object_key
288 pk = std::make_shared<special_mflsum_key>(pf);
290 build_methods.push_back(pf);
291 situations[pfems] = pf;
296 is_adapted =
true; touch();
bool context_check() const
return true if update_from_context was called
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
void set_finite_element(size_type cv, pfem pf)
Set the finite element method of a convex.
const dal::bit_vector & convex_index() const
Get the set of convexes where a finite element has been assigned.
Implement a special mesh_fem with merges the FEMs of two (or more) mesh_fems.
void copy(const L1 &l1, L2 &l2)
*/
pdof_description derivative_dof(dim_type d, dim_type r)
Description of a unique dof of derivative type.
pdof_description lagrange_dof(dim_type d)
Description of a unique dof of lagrange type (value at the node).
pdof_description global_dof(dim_type d)
Description of a global dof, i.e.
dof_description * pdof_description
Type representing a pointer on a dof_description.
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
pfem_precomp fem_precomp(pfem pf, bgeot::pstored_point_tab pspt, dal::pstatic_stored_object dep)
Handles precomputations for FEM.
gmm::uint16_type short_type
used as the common short type integer in the library
size_t size_type
used as the common size type in the library
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
void del_stored_object(const pstatic_stored_object &o, bool ignore_unstored)
Delete an object and the object which depend on it.
GEneric Tool for Finite Element Methods.