27 void fem_sum::init() {
28 cvr = pfems[0]->ref_convex(cv);
29 dim_ = cvr->structure()->dim();
30 is_equiv = !smart_global_dof_linking_;
31 real_element_defined =
true;
32 is_polycomp = is_pol = is_lag = is_standard_fem =
false;
37 nm <<
"FEM_SUM(" << pfems[0]->debug_name() <<
",";
38 for (
size_type i = 1; i < pfems.size(); ++i)
39 nm << pfems[i]->debug_name() <<
",";
40 nm <<
" cv:" << cv <<
")";
41 debug_name_ = nm.str();
44 for (
size_type i = 0; i < pfems.size(); ++i) {
45 GMM_ASSERT1(pfems[i]->target_dim() == 1,
"Vectorial fems not supported");
47 for (
size_type k = 0; k < pfems[i]->nb_dof(cv); ++k) {
48 add_node(pfems[i]->dof_types()[k], pfems[i]->node_of_dof(cv,k));
54 void fem_sum::mat_trans(base_matrix &M,
62 std::vector<pdof_description> hermdof(dim());
63 for (dim_type
id = 0;
id < dim(); ++id)
66 gmm::copy(gmm::identity_matrix(), M);
67 base_vector val(1), val2(1);
68 base_matrix grad(1, dim());
71 for (
size_type ifem1 = 0, i=0; ifem1 < pfems.size(); ++ifem1) {
72 pfem pf1 = pfems[ifem1];
74 for (
size_type idof1 = 0; idof1 < pf1->nb_dof(cv); ++idof1, ++i) {
75 if (pf1->dof_types()[idof1] == gdof) {
76 base_vector coeff(pfems[ifem1]->nb_dof(cv));
78 fem_interpolation_context fic(pgt, pf1, base_node(dim()), G, cv);
79 for (
size_type ifem2 = 0, j=0; ifem2 < pfems.size(); ++ifem2) {
80 pfem pf2 = pfems[ifem2];
81 fem_interpolation_context fic2(pgt, pf2, base_node(dim()), G, cv);
82 for (
size_type idof2 = 0; idof2 < pf2->nb_dof(cv); ++idof2, ++j) {
86 base_vector coeff2(pfems[ifem2]->nb_dof(cv));
90 fic.set_xref(pf2->node_of_dof(cv, idof2));
91 fic2.set_xref(pf2->node_of_dof(cv, idof2));
92 if (dof_weak_compatibility(pdd, lagdof) == 0) {
93 pfems[ifem1]->interpolation(fic, coeff, val, 1);
95 pfems[ifem2]->interpolation(fic2, coeff2, val2, 1);
97 M(i, j) = -val[0]*val2[0];
105 else for (
size_type id = 0;
id < dim(); ++id) {
106 if (dof_weak_compatibility(pdd, hermdof[
id]) == 0) {
107 pfems[ifem1]->interpolation_grad(fic, coeff, grad, 1);
108 M(i, j) = -grad(0,
id);
109 cout <<
"dof " << idof2 <<
"compatible with hermite " 115 "Sorry, smart_global_dof_linking not " 116 "compatible with this kind of dof");
130 for (
size_type i = 0; i < pfems.size(); ++i) {
132 if (j >= nb) j -= pfems[i]->nb_dof(cv);
133 else return pfems[i]->index_of_global_dof(cv, j);
135 GMM_ASSERT1(
false,
"incoherent global dof.");
138 void fem_sum::base_value(
const base_node &,
140 { GMM_ASSERT1(
false,
"No base values, real only element."); }
141 void fem_sum::grad_base_value(
const base_node &,
143 { GMM_ASSERT1(
false,
"No base values, real only element."); }
144 void fem_sum::hess_base_value(
const base_node &,
146 { GMM_ASSERT1(
false,
"No base values, real only element."); }
148 void fem_sum::real_base_value(
const fem_interpolation_context &c,
151 bgeot::multi_index mi(2);
152 mi[1] = target_dim(); mi[0] =
short_type(nb_dof(0));
154 base_tensor::iterator it = t.begin(), itf;
156 fem_interpolation_context c0 = c;
157 std::vector<base_tensor> val_e(pfems.size());
158 for (
size_type k = 0; k < pfems.size(); ++k) {
160 c0.set_pfp(
fem_precomp(pfems[k], c0.pfp()->get_ppoint_tab(),
162 }
else { c0.set_pf(pfems[k]); }
163 c0.base_value(val_e[k]);
166 for (dim_type q = 0; q < target_dim(); ++q) {
167 for (
size_type k = 0; k < pfems.size(); ++k) {
168 itf = val_e[k].begin() + q * pfems[k]->nb_dof(cv);
169 for (
size_type i = 0; i < pfems[k]->nb_dof(cv); ++i)
173 assert(it == t.end());
174 if (!is_equivalent() && withM) {
176 t.mat_transp_reduction(tt, c.M(), 0);
181 void fem_sum::real_grad_base_value(
const fem_interpolation_context &c,
182 base_tensor &t,
bool withM)
const {
183 bgeot::multi_index mi(3);
184 mi[2] =
short_type(c.N()); mi[1] = target_dim();
187 base_tensor::iterator it = t.begin(), itf;
189 fem_interpolation_context c0 = c;
190 std::vector<base_tensor> grad_e(pfems.size());
191 for (
size_type k = 0; k < pfems.size(); ++k) {
193 c0.set_pfp(
fem_precomp(pfems[k], c0.pfp()->get_ppoint_tab(),
195 }
else { c0.set_pf(pfems[k]); }
196 c0.grad_base_value(grad_e[k]);
199 for (dim_type k = 0; k < c.N() ; ++k) {
200 for (dim_type q = 0; q < target_dim(); ++q) {
201 for (
size_type f = 0; f < pfems.size(); ++f) {
202 itf = grad_e[f].begin()
203 + (k * target_dim() + q) * pfems[f]->nb_dof(cv);
204 for (
size_type i = 0; i < pfems[f]->nb_dof(cv); ++i)
209 assert(it == t.end());
210 if (!is_equivalent() && withM) {
212 t.mat_transp_reduction(tt, c.M(), 0);
216 void fem_sum::real_hess_base_value(
const fem_interpolation_context &c,
217 base_tensor &t,
bool withM)
const {
218 t.adjust_sizes(nb_dof(0), target_dim(), gmm::sqr(c.N()));
219 base_tensor::iterator it = t.begin(), itf;
221 fem_interpolation_context c0 = c;
222 std::vector<base_tensor> hess_e(pfems.size());
223 for (
size_type k = 0; k < pfems.size(); ++k) {
225 c0.set_pfp(
fem_precomp(pfems[k], c0.pfp()->get_ppoint_tab(),
227 }
else { c0.set_pf(pfems[k]); }
228 c0.hess_base_value(hess_e[k]);
231 dim_type NNdim = dim_type(gmm::sqr(c.N())*target_dim());
232 for (dim_type jkq = 0; jkq < NNdim ; ++jkq) {
233 for (
size_type f = 0; f < pfems.size(); ++f) {
234 itf = hess_e[f].begin() + (jkq * pfems[f]->nb_dof(cv));
235 for (
size_type i = 0; i < pfems[f]->nb_dof(cv); ++i)
239 assert(it == t.end());
240 if (!is_equivalent() && withM) {
242 t.mat_transp_reduction(tt, c.M(), 0);
246 void mesh_fem_sum::clear_build_methods() {
247 for (
size_type i = 0; i < build_methods.size(); ++i)
249 build_methods.clear();
251 void mesh_fem_sum::clear(
void) {
253 clear_build_methods();
258 DAL_SIMPLE_KEY(special_mflsum_key,
pfem);
260 void mesh_fem_sum::adapt(
void) {
264 for (
size_type i = 0; i < mfs.size(); ++i)
266 "Sorry fem_sum for reduced mesh_fem is not implemented");
269 std::vector<pfem> pfems;
270 bool is_cv_dep =
false;
271 for (
size_type j = 0; j < mfs.size(); ++j) {
273 pfem pf = mfs[j]->fem_of_element(i);
276 if (pf->is_on_real_element()) is_cv_dep =
true;
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();
dof_description * pdof_description
Type representing a pointer on a dof_description.
Implement a special mesh_fem with merges the FEMs of two (or more) mesh_fems.
void del_stored_object(const pstatic_stored_object &o, bool ignore_unstored)
Delete an object and the object which depend on it.
size_t size_type
used as the common size type in the library
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
pdof_description derivative_dof(dim_type d, dim_type r)
Description of a unique dof of derivative type.
void set_finite_element(size_type cv, pfem pf)
Set the finite element method of a convex.
bool is_reduced() const
Return true if a reduction matrix is applied to the dofs.
GEneric Tool for Finite Element Methods.
pdof_description lagrange_dof(dim_type d)
Description of a unique dof of lagrange type (value at the node).
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
gmm::uint16_type short_type
used as the common short type integer in the library
pfem_precomp fem_precomp(pfem pf, bgeot::pstored_point_tab pspt, dal::pstatic_stored_object dep)
Handles precomputations for FEM.
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
bool context_check() const
return true if update_from_context was called
const dal::bit_vector & convex_index() const
Get the set of convexes where a finite element has been assigned.
pdof_description global_dof(dim_type d)
Description of a global dof, i.e.
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation