@@ -80,16 +80,40 @@ struct fe_de_elliptic {
8080 requires (is_valid_info_t <InfoT>::value)
8181 fe_de_elliptic (const GeoFrame& gf, InfoT&& info) {
8282 fdapde_static_assert (GeoFrame::Order == 1 , THIS_CLASS_IS_FOR_ORDER_ONE_GEOFRAMES_ONLY);
83- using BilinearForm = std::tuple_element_t <0 , std::decay_t <decltype (info.penalty )>>;
83+ discretize (gf, info.penalty );
84+ analyze_data (gf);
85+ }
86+
87+ // perform finite element based numerical discretization
88+ template <typename GeoFrame, typename Penalty> void discretize (const GeoFrame& gf, Penalty&& penalty) {
89+ fdapde_static_assert (internals::is_valid_penalty_pair_v<Penalty>, INVALID_PENALTY_DESCRIPTION);
90+ using BilinearForm = std::tuple_element_t <0 , std::decay_t <Penalty>>;
91+ using LinearForm = std::tuple_element_t <1 , std::decay_t <Penalty>>;
8492 using FeSpace = typename BilinearForm::TrialSpace;
8593 using DofHandler = typename FeSpace::DofHandlerType;
8694 using Triangulation = typename FeSpace::Triangulation;
8795 constexpr int embed_dim = Triangulation::embed_dim;
88- const Triangulation& triangulation = gf.template triangulation <0 >();
89- const FeSpace& fe_space = std::get<0 >(info.penalty ).trial_space ();
90- const DofHandler& dof_handler = fe_space.dof_handler ();
9196
92- discretize (info.penalty );
97+ // discretization
98+ const FeSpace& fe_space = std::get<0 >(penalty).trial_space ();
99+ const Triangulation& triangulation = gf.template triangulation <0 >();
100+ const DofHandler& dof_handler = fe_space.dof_handler ();
101+ const BilinearForm& bilinear_form = std::get<0 >(penalty);
102+ const LinearForm& linear_form = std::get<1 >(penalty);
103+ n_dofs_ = bilinear_form.n_dofs (); // number of basis functions over physical domain
104+ internals::fe_mass_assembly_loop<FeSpace> mass_assembler (bilinear_form.trial_space ());
105+ R0_ = mass_assembler.assemble ();
106+ R1_ = bilinear_form.assemble ();
107+ u_ = linear_form.assemble ();
108+
109+ // penalty matrix
110+ sparse_solver_t invR0;
111+ invR0.compute (R0_);
112+ P_ = R1_.transpose () * invR0.solve (R1_);
113+ // store handles for basis system evaluation at locations
114+ point_eval_ = [fe_space = bilinear_form.trial_space ()](const matrix_t & locs) -> decltype (auto ) {
115+ return internals::point_basis_eval (fe_space, locs);
116+ };
93117 // eval reference basis at quadrature nodes, store de_quadrature weights
94118 de_quadrature_t <embed_dim> quad_rule;
95119 int n_quad_nodes = quad_rule.order ;
@@ -103,15 +127,15 @@ struct fe_de_elliptic {
103127 w[i] = quad_rule.weights [i];
104128 }
105129 // store handle for approximation of \int_D (e^g)
106- int_exp_ = [&, PsiQuad, w](const vector_t & g) {
130+ int_exp_ = [&, dof_handler, PsiQuad, w](const vector_t & g) {
107131 double val_ = 0 ;
108132 for (auto it = triangulation.cells_begin (); it != triangulation.cells_end (); ++it) {
109133 val_ += w.dot ((PsiQuad * g (dof_handler.dofs ().row (it->id ()))).array ().exp ().matrix ()) * it->measure ();
110134 }
111135 return val_;
112136 };
113137 // store handle for approximation of \nabla_g(\int_D (e^g))
114- grad_int_exp_ = [&, PsiQuad, w](const vector_t & g) {
138+ grad_int_exp_ = [&, dof_handler, PsiQuad, w](const vector_t & g) {
115139 vector_t grad = vector_t::Zero (g.rows ());
116140 for (auto it = triangulation.cells_begin (); it != triangulation.cells_end (); ++it) {
117141 grad (dof_handler.dofs ().row (it->id ())) +=
@@ -120,33 +144,7 @@ struct fe_de_elliptic {
120144 it->measure ();
121145 }
122146 return grad;
123- };
124-
125- analyze_data (gf);
126- }
127-
128- // perform finite element based numerical discretization
129- template <typename Penalty> void discretize (Penalty&& penalty) {
130- fdapde_static_assert (internals::is_valid_penalty_pair_v<Penalty>, INVALID_PENALTY_DESCRIPTION);
131- using BilinearForm = std::tuple_element_t <0 , std::decay_t <Penalty>>;
132- using LinearForm = std::tuple_element_t <1 , std::decay_t <Penalty>>;
133- using FeSpace = typename BilinearForm::TrialSpace;
134- // discretization
135- const BilinearForm& bilinear_form = std::get<0 >(penalty);
136- const LinearForm& linear_form = std::get<1 >(penalty);
137- n_dofs_ = bilinear_form.n_dofs (); // number of basis functions over physical domain
138- internals::fe_mass_assembly_loop<FeSpace> mass_assembler (bilinear_form.trial_space ());
139- R0_ = mass_assembler.assemble ();
140- R1_ = bilinear_form.assemble ();
141- u_ = linear_form.assemble ();
142- // penalty matrix
143- sparse_solver_t invR0;
144- invR0.compute (R0_);
145- P_ = R1_.transpose () * invR0.solve (R1_);
146- // store handles for basis system evaluation at locations
147- point_eval_ = [fe_space = bilinear_form.trial_space ()](const matrix_t & locs) -> decltype (auto ) {
148- return internals::point_basis_eval (fe_space, locs);
149- };
147+ };
150148 return ;
151149 }
152150 // fit from geoframe
0 commit comments