36 dim, LinearAlgebra::distributed::Vector<Number>> {
38 using VectorType = LinearAlgebra::distributed::Vector<Number>;
42 MatrixFreeOperators::Base<dim,
43 LinearAlgebra::distributed::Vector<Number>>;
48 ADROperator() : problem_ptr(nullptr), is_mg_level(false), mg_level(-1) {}
59 Base::initialize(data_in);
60 this->problem_ptr = &problem;
61 this->is_mg_level =
false;
63 precompute_coefficient_data();
75 const MGConstrainedDoFs& mg_constrained_dofs,
77 Base::initialize(data_in, mg_constrained_dofs, level);
78 this->problem_ptr = &problem;
79 this->is_mg_level =
true;
80 this->mg_level = level;
81 precompute_coefficient_data();
89 problem_ptr =
nullptr;
90 diffusion_coefficients.clear();
91 advection_coefficients.clear();
92 reaction_coefficients.clear();
103 this->inverse_diagonal_entries.reset(
new DiagonalMatrix<VectorType>());
105 this->inverse_diagonal_entries->get_vector();
106 this->data->initialize_dof_vector(inverse_diagonal);
108 MatrixFreeTools::compute_diagonal(*this->data, inverse_diagonal,
109 &ADROperator::local_compute_diagonal,
112 this->set_constrained_entries_to_one(inverse_diagonal);
114 for (
unsigned int i = 0; i < inverse_diagonal.locally_owned_size();
116 if (std::abs(inverse_diagonal.local_element(i)) > 1e-14)
117 inverse_diagonal.local_element(i) =
118 1.0 / inverse_diagonal.local_element(i);
120 inverse_diagonal.local_element(i) = 1.0;
141 this->data->cell_loop(&ADROperator::local_apply,
this, dst, src);
151 void precompute_coefficient_data() {
152 Assert(problem_ptr !=
nullptr, ExcNotInitialized());
154 const unsigned int n_cells = this->data->n_cell_batches();
155 const unsigned int n_q_points = Utilities::pow(fe_degree + 1, dim);
157 diffusion_coefficients.resize(n_cells);
158 advection_coefficients.resize(n_cells);
159 reaction_coefficients.resize(n_cells);
162 FEEvaluation<dim, fe_degree, fe_degree + 1, 1, Number> phi(*this->data);
164 for (
unsigned int cell = 0; cell < n_cells; ++cell) {
167 diffusion_coefficients[cell].resize(n_q_points);
168 advection_coefficients[cell].resize(n_q_points);
169 reaction_coefficients[cell].resize(n_q_points);
171 for (
unsigned int q = 0; q < n_q_points; ++q) {
173 Point<dim, VectorizedArray<Number>> q_point =
174 phi.quadrature_point(q);
177 VectorizedArray<Number> mu;
178 Tensor<1, dim, VectorizedArray<Number>> beta;
179 VectorizedArray<Number> gamma;
181 for (
unsigned int v = 0; v < VectorizedArray<Number>::size();
184 for (
unsigned int d = 0; d < dim; ++d)
185 p[d] = q_point[d][v];
187 mu[v] = problem_ptr->diffusion_coefficient(p);
188 gamma[v] = problem_ptr->reaction_coefficient(p);
190 Tensor<1, dim> beta_scalar =
191 problem_ptr->advection_field(p);
192 for (
unsigned int d = 0; d < dim; ++d)
193 beta[d][v] = beta_scalar[d];
196 diffusion_coefficients[cell][q] = mu;
197 advection_coefficients[cell][q] = beta;
198 reaction_coefficients[cell][q] = gamma;
216 const std::pair<unsigned int, unsigned int>& cell_range)
const {
217 FEEvaluation<dim, fe_degree, fe_degree + 1, 1, Number> phi(*this->data);
219 for (
unsigned int cell = cell_range.first; cell < cell_range.second;
222 phi.gather_evaluate(src, EvaluationFlags::values |
223 EvaluationFlags::gradients);
225 for (
unsigned int q = 0; q < phi.n_q_points; ++q) {
227 const VectorizedArray<Number>& mu_val =
228 diffusion_coefficients[cell][q];
229 const Tensor<1, dim, VectorizedArray<Number>>& beta_val =
230 advection_coefficients[cell][q];
231 const VectorizedArray<Number>& gamma_val =
232 reaction_coefficients[cell][q];
234 const auto u_val = phi.get_value(q);
235 const auto grad_u = phi.get_gradient(q);
238 const auto flux = mu_val * grad_u;
242 const auto val = gamma_val * u_val + beta_val * grad_u;
244 phi.submit_gradient(flux, q);
245 phi.submit_value(val, q);
248 phi.integrate_scatter(
249 EvaluationFlags::values | EvaluationFlags::gradients, dst);
259 void local_compute_diagonal(
260 FEEvaluation<dim, fe_degree, fe_degree + 1, 1, Number>& phi)
const {
261 const unsigned int cell = phi.get_current_cell_index();
263 phi.evaluate(EvaluationFlags::values | EvaluationFlags::gradients);
265 for (
unsigned int q = 0; q < phi.n_q_points; ++q) {
266 const VectorizedArray<Number> u_val = phi.get_value(q);
267 const Tensor<1, dim, VectorizedArray<Number>> grad_u =
271 const Tensor<1, dim, VectorizedArray<Number>> flux =
272 diffusion_coefficients[cell][q] * grad_u;
274 const VectorizedArray<Number> advection_val =
275 advection_coefficients[cell][q] * grad_u;
277 const VectorizedArray<Number> val =
278 reaction_coefficients[cell][q] * u_val + advection_val;
280 phi.submit_gradient(flux, q);
281 phi.submit_value(val, q);
284 phi.integrate(EvaluationFlags::values | EvaluationFlags::gradients);
288 const ProblemInterface<dim>* problem_ptr;
290 unsigned int mg_level;
294 std::vector<std::vector<VectorizedArray<Number>>> diffusion_coefficients;
295 std::vector<std::vector<Tensor<1, dim, VectorizedArray<Number>>>>
296 advection_coefficients;
297 std::vector<std::vector<VectorizedArray<Number>>> reaction_coefficients;