Reduced Lagrange Multipliers
 
Loading...
Searching...
No Matches
inclusions.h
Go to the documentation of this file.
1// ---------------------------------------------------------------------
2//
3// Copyright (C) 2024 by Luca Heltai
4//
5// This file is part of the reduced_lagrange_multipliers application, based on
6// the deal.II library.
7//
8// The reduced_lagrange_multipliers application is free software; you can use
9// it, redistribute it, and/or modify it under the terms of the Apache-2.0
10// License WITH LLVM-exception as published by the Free Software Foundation;
11// either version 3.0 of the License, or (at your option) any later version. The
12// full text of the license can be found in the file LICENSE.md at the top level
13// of the reduced_lagrange_multipliers distribution.
14//
15// ---------------------------------------------------------------------
16
27#ifndef rdlm_inclusions
28#define rdlm_inclusions
29
30#include <deal.II/base/hdf5.h>
33
35
38
43
45
46#include <boost/algorithm/string.hpp>
47
48#include <fstream>
49
50using namespace dealii;
51
52
63template <int spacedim>
65{
66public:
67 template <int dim, typename number, int n_components>
68 friend class CouplingOperator;
69
75 Inclusions(const unsigned int n_vector_components = 1)
76 : ParameterAcceptor("/Immersed Problem/Immersed inclusions")
77 , inclusions_rhs("/Immersed Problem/Immersed inclusions/Boundary data",
80 {
81 static_assert(spacedim > 1, "Not implemented in dim = 1");
82 add_parameter("Inclusions refinement", n_q_points);
83 add_parameter("Inclusions", inclusions);
84 add_parameter("Reference inclusion data", reference_inclusion_data);
85
87 "Number of fourier coefficients",
89 "This represents the number of scalar harmonic functions used "
90 "for the representation of the data (boundary data or forcing data) "
91 "of the inclusion. The provided input files should contain at least "
92 "a number of entries which is equal to this number multiplied by the "
93 "number of vector components of the problem. Any additional entry is "
94 "ignored by program. If fewer entries are specified, an exception is "
95 "thrown.");
97 "Selection of Fourier coefficients",
99 "This allows one to select a subset of the components of the harmonic functions "
100 "used for the representation of the data (boundary data or forcing data). Notice "
101 "that these indices are w.r.t. to the total number of components of the problem, "
102 "that is, number of Fourier coefficients x number of vector components. In "
103 "particular any entry of this list must be in the set "
104 "[0,n_coefficients*n_vector_components). ");
105 add_parameter("Bounding boxes extraction level", rtree_extraction_level);
106 add_parameter("Inclusions file", inclusions_file);
107 add_parameter("Data file", data_file);
108
109 auto reset_function = [this]() {
110 this->prm.set("Function expression",
111 (spacedim == 2 ? "0; 0" : "0; 0; 0"));
112 };
113 inclusions_rhs.declare_parameters_call_back.connect(reset_function);
114 }
115
116
123 n_dofs() const
124 {
125 return inclusions.size() * n_dofs_per_inclusion();
126 }
127
128
136 {
137 return inclusions.size() * n_q_points;
138 }
139
140
148 {
149 return inclusions.size();
150 }
151
157 unsigned int
159 {
160 // return n_coefficients * n_vector_components;
161 return selected_coefficients.size();
162 }
163
167 void
169 {
171 ExcMessage(
172 "Refinement of inclusions must be greater than zero."));
174 ExcMessage(
175 "Number of coefficients must be greater than zero."));
177 normals.resize(n_q_points);
178 theta.resize(n_q_points);
180
181 for (unsigned int i = 0; i < n_q_points; ++i)
182 {
183 theta[i] = i * 2 * numbers::PI / n_q_points;
184 support_points[i][0] = std::cos(theta[i]);
185 support_points[i][1] = std::sin(theta[i]);
186 normals[i] = support_points[i];
187 }
188
189 // Make sure that selected coefficients is the iota vector, when we don't
190 // select anything for backward compatibility.
191 if (selected_coefficients.empty())
192 {
194 for (unsigned int i = 0; i < n_coefficients * n_vector_components; ++i)
196 }
197
198 // This MUST be here, otherwise n_dofs_per_inclusions() would be wrong.
200
201 if (inclusions_file != "")
202 {
203 std::ifstream infile(inclusions_file);
204 Assert(infile, ExcIO());
205
206 double buffer_double;
207 // cx, cy, R or cx,cy,cz,dx,dy,dz,R,vesselID
208 const unsigned int size = (spacedim == 2 ? 3 : 8);
209 std::vector<double> inclusion(size);
210
211 while (infile >> buffer_double)
212 {
213 inclusion[0] = buffer_double;
214 for (unsigned int i = 1; i < size; ++i)
215 {
216 Assert(infile, ExcIO());
217 infile >> inclusion[i];
218 }
219 inclusions.push_back(inclusion);
220 }
221 }
222
223 if (data_file != "")
224 {
225 std::ifstream infile(data_file);
226 Assert(infile, ExcIO());
227
228 std::string line;
229 while (std::getline(infile, line))
230 {
231 std::vector<double> double_line;
232 std::istringstream iss(line);
233 double buffer_double;
234 while (iss >> buffer_double)
235 {
236 double_line.push_back(buffer_double);
237 }
238 inclusions_data.push_back(double_line);
239 }
241 ExcDimensionMismatch(inclusions_data.size(),
242 n_inclusions()));
243 if (inclusions_data.size() > 0)
244 {
245 const auto N = inclusions_data[0].size();
246 for (const auto &l : inclusions_data)
247 {
248 AssertThrow(l.size() == N, ExcDimensionMismatch(l.size(), N));
249 }
251 {
252 std::cout << "rank "
254 << ": Read " << N << " coefficients per "
255 << inclusions.size() << " inclusion" << std::endl;
256 }
257 }
258 }
259 else
260 {
261 while (inclusions_data.size() < inclusions.size())
262 {
264 }
265 }
267 }
268
269
276 std::vector<types::global_dof_index>
277 get_dof_indices(const types::global_dof_index &quadrature_id) const
278 {
279 AssertIndexRange(quadrature_id, n_particles());
280 std::vector<types::global_dof_index> dofs(n_dofs_per_inclusion());
281 auto start_index = (quadrature_id / n_q_points) * n_dofs_per_inclusion();
282 for (auto &d : dofs)
283 d = start_index++;
284 return dofs;
285 }
286
292 void
295 {
297 initialize();
298 // compute_rotated_inclusion_data();
299
300 inclusions_as_particles.initialize(tria,
302
303 if (n_dofs() == 0)
304 return;
305
306 // Only add particles once.
307 auto inclusions_set =
309 n_inclusions());
310
311 std::vector<Point<spacedim>> particles_positions;
312 particles_positions.reserve(n_particles());
313 for (const auto i : inclusions_set)
314 {
315 const auto &p = get_current_support_points(i);
316 particles_positions.insert(particles_positions.end(),
317 p.begin(),
318 p.end());
319 }
320
321 std::vector<BoundingBox<spacedim>> all_boxes;
322 all_boxes.reserve(tria.n_locally_owned_active_cells());
323 for (const auto &cell : tria.active_cell_iterators())
324 if (cell->is_locally_owned())
325 all_boxes.emplace_back(cell->bounding_box());
326 const auto tree = pack_rtree(all_boxes);
327 const auto local_boxes = extract_rtree_level(tree, rtree_extraction_level);
328
329 auto global_bounding_boxes =
331
332 Assert(!global_bounding_boxes.empty(),
333 ExcInternalError(
334 "I was expecting the "
335 "global_bounding_boxes to be filled at this stage. "
336 "Make sure you fill this vector before trying to use it "
337 "here. Bailing out."));
338 inclusions_as_particles.insert_global_particles(particles_positions,
339 global_bounding_boxes);
340
341 // Sanity check.
342 AssertDimension(inclusions_as_particles.n_global_particles(),
343 n_particles());
344 }
345
353 get_inclusion_id(const types::global_dof_index &quadrature_id) const
354 {
355 AssertIndexRange(quadrature_id, n_particles());
356 return (quadrature_id / n_q_points);
357 }
358
365 inline unsigned int
367 {
368 AssertIndexRange(dof_index, n_dofs());
369 // return dof_index % n_vector_components;
370 return selected_coefficients[dof_index % n_dofs_per_inclusion()] %
372 }
373
374
381 inline unsigned int
383 {
384 AssertIndexRange(dof_index, n_dofs());
385 // return dof_index % n_vector_components;
386 return selected_coefficients[dof_index % n_dofs_per_inclusion()];
387 }
388
389
397 inline double
399 const types::global_dof_index &dof_index) const
400 {
401 AssertIndexRange(inclusion_id, n_inclusions());
402 AssertIndexRange(dof_index, n_dofs());
403 // return dof_index % n_vector_components;
405 inclusion_id)[get_fourier_component(dof_index)];
406 }
407
416 inline double
418 const types::global_dof_index &dof_index,
419 const Point<spacedim> &point) const
420 {
421 AssertIndexRange(inclusion_id, n_inclusions());
422 AssertIndexRange(dof_index, n_dofs());
423 // return dof_index % n_vector_components;
424 if (inclusions_data.size() > 0) // If we have data
425 {
426 if (n_vector_components == 1)
427 return inclusions_data[inclusion_id]
428 [get_fourier_component(dof_index)];
429 else if (n_vector_components == spacedim)
430 {
432 inclusion_id)[get_fourier_component(dof_index)];
433 }
434 else
435 {
436 AssertThrow(false, ExcNotImplemented());
437 return 0.0;
438 }
439 }
440 else
441 {
442 return inclusions_rhs.value(point, get_fourier_component(dof_index));
443 }
444 }
445
446
447
454 inline const Tensor<1, spacedim> &
455 get_normal(const types::global_dof_index &quadrature_id) const
456 {
457 AssertIndexRange(quadrature_id, n_particles());
458 if constexpr (spacedim == 2)
459 return (normals[quadrature_id % n_q_points]);
460 else
461 {
462 const auto inclusion_id = get_inclusion_id(quadrature_id);
463 const auto rotation = get_rotation(inclusion_id);
464 return (rotation * normals[quadrature_id % n_q_points]);
465 }
466 }
467
474 inline double
475 get_JxW(const types::global_dof_index &particle_id) const
476 {
477 AssertIndexRange(particle_id, n_particles());
478 const auto id = particle_id / n_q_points;
479 AssertIndexRange(id, inclusions.size());
480 const auto r = get_radius(id);
481 return 2 * numbers::PI * r / n_q_points * get_direction(id).norm();
482 }
483
484
491 const std::vector<double> &
492 get_fe_values(const types::global_dof_index particle_id) const
493 {
494 AssertIndexRange(particle_id, n_particles());
495 if (n_coefficients == 0)
496 return current_fe_values;
497 const auto q = particle_id % n_q_points;
498 const auto id = particle_id / n_q_points;
499 AssertIndexRange(id, inclusions.size());
500 (void)id;
501 const auto r = get_radius(id);
502 (void)r;
503 const auto s0 = 1.0;
504 const auto s1 = std::sqrt(2);
505
506 unsigned int basis_local_id = 0;
507 for (unsigned int basis :
508 selected_coefficients) // 0; basis < n_coefficients *
509 // n_vector_components;
510 //++basis)
511 {
512 const unsigned int fourier_index =
513 basis / n_vector_components + 0; // coefficient_offset;
514 unsigned int omega = (fourier_index + 1) / 2;
515
516 double scaling_factor = (omega == 1 ? 1 : s1);
517
518 if (fourier_index == 0)
519 current_fe_values[basis_local_id] = s0;
520 else if ((fourier_index - 1) % 2 == 0)
521 current_fe_values[basis_local_id] =
522 scaling_factor * std::cos(theta[q] * omega);
523 else
524 current_fe_values[basis_local_id] =
525 scaling_factor * std::sin(theta[q] * omega);
526 ++basis_local_id;
527 }
528 // for (unsigned int c = 0; c < n_coefficients; ++c)
529 // {
530 // unsigned int omega = (c + coefficient_offset + 1) / 2;
531 // const double rho = std::pow(r, omega);
532 // for (unsigned int i = 0; i < n_vector_components; ++i)
533 // if ((std::max(c + coefficient_offset, 1u) + 1) % 2 == 0)
534 // current_fe_values[c * n_vector_components + i] =
535 // rho * std::cos(theta[q] * omega);
536 // else
537 // current_fe_values[c * n_vector_components + i] =
538 // rho * std::sin(theta[q] * omega);
539 // }
540 return current_fe_values;
541 }
542
543
551 get_center(const types::global_dof_index &inclusion_id) const
552 {
553 AssertIndexRange(inclusion_id, inclusions.size());
554 const auto &inclusion = inclusions[inclusion_id];
555 Assert(inclusion.size() > spacedim, ExcInternalError());
556 Point<spacedim> center;
557 for (unsigned int d = 0; d < spacedim; ++d)
558 center[d] = inclusion[d];
559 return center;
560 }
561
562
569 double
570 get_radius(const types::global_dof_index &inclusion_id) const
571 {
572 AssertIndexRange(inclusion_id, inclusions.size());
573 const auto &inclusion = inclusions[inclusion_id];
574 if constexpr (spacedim == 2)
575 {
576 AssertDimension(inclusion.size(), spacedim + 1);
577 return inclusion[spacedim];
578 }
579 else
580 {
581 AssertDimension(inclusion.size(), 2 * spacedim + 2);
582 return inclusion[2 * spacedim];
583 }
584 }
585
592 double
594 {
595 auto r = get_radius(inclusion_id);
596 if constexpr (spacedim == 2)
597 return 2 * numbers::PI * r;
598 else
599 {
600 auto ds = get_direction(inclusion_id).norm();
601 return 2 * numbers::PI * r * ds;
602 }
603 }
604
605
613 get_direction(const types::global_dof_index &inclusion_id) const
614 {
615 AssertIndexRange(inclusion_id, inclusions.size());
616 if constexpr (spacedim == 2)
617 {
618 // No direction in 2d. But the norm is used.
620 ret[0] = 1.0;
621 return ret;
622 }
623 else
624 {
625 const auto &inclusion = inclusions[inclusion_id];
626 AssertDimension(inclusion.size(), 2 * spacedim + 2);
627 Tensor<1, spacedim> direction;
628 for (unsigned int d = 0; d < spacedim; ++d)
629 direction[d] = inclusion[spacedim + d];
630 AssertThrow(direction.norm() > 1e-10,
631 ExcMessage("Expecting a direction with non-zero norm"));
632 return direction;
633 }
634 }
635
636
644 get_rotation(const types::global_dof_index &inclusion_id) const
645 {
647 if constexpr (spacedim == 2)
648 {
649 return rotation;
650 }
651 else if constexpr (spacedim == 3)
652 {
653 auto direction = get_direction(inclusion_id);
654 direction /= direction.norm();
655
656 // Build rotation w.r.t. z axis
657 static const auto z_axis = Tensor<1, spacedim>({0, 0, 1});
658 auto v = cross_product_3d(z_axis, direction);
659 const auto cos_t = direction * z_axis;
660
661 if (std::abs(cos_t + 1) < 1e-10)
662 {
663 rotation[1][1] = -1;
664 rotation[2][2] = -1;
665 }
666 else
667 {
669 vx[0] = Tensor<1, spacedim>({0, -v[2], v[1]});
670 vx[1] = Tensor<1, spacedim>({v[2], 0, -v[0]});
671 vx[2] = Tensor<1, spacedim>({-v[1], v[0], 0});
672 auto vx2 = vx * vx;
673 rotation += vx + vx2 * (1 / (1 + cos_t));
674 }
675
676 return rotation;
677 }
678 }
679
680
681
682 const std::vector<Point<spacedim>> &
684 {
685 const auto center = get_center(inclusion_id);
686 const auto radius = get_radius(inclusion_id);
687 const auto rotation = get_rotation(inclusion_id);
688
689 for (unsigned int q = 0; q < n_q_points; ++q)
691 center + rotation * (support_points[q] * radius);
693 }
694
695
701 void
702 output_particles(const std::string &filename) const
703 {
704 Particles::DataOut<spacedim> particles_out;
706 particles_out.write_vtu_in_parallel(filename, mpi_communicator);
707 }
708
712 void
714 {
715#ifdef DEAL_II_WITH_HDF5
716 //
717 inclusions_data.clear();
719 data_file_h = std::make_unique<HDF5::File>(data_file,
720 HDF5::File::FileAccessMode::open,
722 auto group = data_file_h->open_group("data");
723 // Read new displacement
724 {
725 auto h5data = group.open_dataset("displacement_data");
726 auto vector_of_data = h5data.template read<Vector<double>>();
727
728 auto inclusions_set =
730 n_inclusions());
731 for (const auto i : inclusions_set)
732 {
733 AssertIndexRange(i, vector_of_data.size());
734 inclusions_data[i] = vector_of_data[i];
735 }
736 }
737 // check that the new data is size consistente
738 const auto N = inclusions_data[0].size();
739 for (const auto &l : inclusions_data)
740 {
741 AssertThrow(l.size() == N, ExcDimensionMismatch(l.size(), N));
742 }
743
744 // data from file should respect the input file standard, i.e. be given in
745 // relative coordinates then we need to rotate it to obtain data in
746 // absolute coordinates compute_rotated_inclusion_data();
747
748#else
749 AssertThrow(false, ExcNeedsHDF5());
750#endif
751 }
752
758 void
759 update_inclusions_data(std::vector<double> new_data)
760 {
761 if constexpr (spacedim == 2)
762 return;
763
764 // if (new_data.size() != 0 && inclusions.size() == 0)
765
766 if (new_data.size() == n_vessels)
767 {
768 std::map<unsigned int, std::vector<types::global_dof_index>>::iterator
769 it = map_vessel_inclusions.begin();
770 while (it != map_vessel_inclusions.end())
771 {
772 // inclusions_data[it->second] = {new_data[it->first],
773 // 0,0,0,new_data[it->first]};
774 for (auto inclusion_id : it->second)
776 new_data[it->first]);
777 ++it;
778 }
779 }
780 else if (new_data.size() == inclusions.size())
781 {
782 for (long unsigned int id = 0; id < new_data.size(); ++id)
784 }
785 else
787 new_data.size() == 0,
788 ExcMessage(
789 "dimensions of new data for the update does not match the inclusions"));
790
791 // compute_rotated_inclusion_data();
792 }
793
794 void
795 update_inclusions_data(std::vector<std::vector<double>> new_data)
796 {
797 if constexpr (spacedim == 2)
798 return;
799
801 new_data.size() == n_vessels,
802 ExcMessage(
803 "dimensions of new data for the update does not match the inclusions"));
804
805 for (unsigned int current_vessel = 0; current_vessel < n_vessels;
806 ++current_vessel)
807 {
808 AssertIndexRange(current_vessel, new_data.size());
809 auto &current_new_data = new_data[current_vessel];
810 auto &current_inclusions = map_vessel_inclusions[current_vessel];
811
812 auto N1 = current_inclusions.size(); // inclusions in vessel
813 auto N2 = current_new_data.size(); // points in new_data
814
816 N2 > 0,
817 ExcMessage(
818 "dimensions of new data for the update does not match the inclusions"));
820 N1 > 1,
821 ExcMessage(
822 "insufficient number of inclusion int the vessel for the update"));
823 if (N2 == 1)
824 {
825 for (unsigned int i = 0; i < N1 - 1; ++i)
826 update_single_inclusion_data_along_normal(i, current_new_data[0]);
827 }
828 else
829 {
830 // compute nv
831 // std::vector<double>
832 double current_vessel_new_data;
833 update_single_inclusion_data_along_normal(0, current_new_data[0]);
834 // current_vessel_new_data.push_back(current_new_data[0]);
835 for (unsigned int i = 1; i < N1 - 1; ++i)
836 {
837 auto X = i / (N1 - 1) * (N2 - 1);
838 auto j = floor(X);
839 Assert(j < N2, ExcInternalError());
840 auto w = X - j;
841 current_vessel_new_data =
842 (1 - w) * current_new_data[j] + (w)*current_new_data[j + 1];
844 i, current_vessel_new_data);
845 // current_vessel_new_data.push_back((1-w)*current_new_data[j]+(w)*current_new_data[j+1]);
846 }
848 current_new_data[N2 - 1]);
849 // current_vessel_new_data.push_back(current_new_data[N2-1]);
850
851 // for (auto inclusion_id : current_inclusions)
852 // {
853 // // assign nv
854 // update_single_inclusion_data_along_normal(inclusion_id,
855 // current_vessel_new_data[inclusion_id]);
856 // }
857 }
858 }
859
860 // compute_rotated_inclusion_data();
861 }
862
870 int
871 get_vesselID(const types::global_dof_index &inclusion_id) const
872 {
873 AssertIndexRange(inclusion_id, inclusions.size());
874 const auto &inclusion = inclusions[inclusion_id];
875 if constexpr (spacedim == 2)
876 {
877 return inclusion_id;
878 }
879 else
880 {
881 AssertDimension(inclusion.size(), 2 * spacedim + 2);
882 return int(inclusion[2 * spacedim + 1]);
883 }
884 }
885
886 void
888 const types::global_dof_index &inclusion_id,
889 const double nd)
890 {
891 AssertIndexRange(inclusion_id, inclusions_data.size());
892 // AssertIndexRange(inclusion_id, inclusions.size());
893 // // update old radius with new value
894 // if constexpr (spacedim == 2)
895 // {
896 // AssertDimension(inclusions[inclusion_id].size(), spacedim + 1);
897 // inclusions[inclusion_id][spacedim] +=
898 // inclusions_data[inclusion_id][0];
899 // }
900 // else
901 // {
902 // AssertDimension(inclusions[inclusion_id].size(), 2 * spacedim + 2);
903 // inclusions[inclusion_id][2 * spacedim] +=
904 // inclusions_data[inclusion_id][0];
905 // }
906 inclusions_data[inclusion_id] = {nd, 0, 0, 0, nd, 0, 0, 0, 0};
907 }
908
909 void
911 const std::vector<double>)
912 {}
913
914 unsigned int
916 {
917 return n_vessels;
918 }
919
920 unsigned int
922 {
923 return n_coefficients;
924 }
925
926 unsigned int
928 {
929 return offset_coefficients;
930 }
931
932 unsigned int
933 get_inclusions_in_vessel(unsigned int vessel_id) const
934 {
935 AssertIndexRange(vessel_id, n_vessels);
936 unsigned int s = map_vessel_inclusions.at(vessel_id).size();
937 return s;
938 }
939
940 void
942 {
944 if constexpr (spacedim == 3)
945 {
946 // const auto locally_owned_inclusions =
947 // Utilities::MPI::create_evenly_distributed_partitioning(
948 // mpi_communicator, n_inclusions());
949 //
950 // for (const auto inclusion_id : locally_owned_inclusions)
951 for (long unsigned int inclusion_id = 0;
952 inclusion_id < inclusions_data.size();
953 ++inclusion_id)
954
955 {
956 auto tensorR = get_rotation(inclusion_id);
957 // std::cout << "tensor: " << tensorR << ", norm :" <<
958 // tensorR.norm() << std::endl; std::cout << "inclusions
959 // data: "; for (auto i : inclusions_data[inclusion_id])
960 // std::cout << i << " ";
961 // std::cout << std::endl;
962 std::vector<double> rotated_phi(
963 inclusions_data[inclusion_id].size());
964 for (long unsigned int phi_i = 0;
965 (phi_i * spacedim + spacedim - 1) <
966 inclusions_data[inclusion_id].size();
967 ++phi_i)
968 {
969 Tensor<1, spacedim> coef_phii;
970 for (unsigned int d = 0; d < spacedim; ++d)
971 coef_phii[d] =
972 inclusions_data[inclusion_id][phi_i * spacedim + d];
973
974 auto rotated_phi_i = tensorR * coef_phii;
975 rotated_phi_i.unroll(&rotated_phi[phi_i * spacedim],
976 &rotated_phi[phi_i * spacedim + 3]);
977 // std::cout << "rotated_phi: ";
978 // for (auto i : rotated_phi)
979 // std::cout << i << " ";
980 // std::cout << std::endl;
981 }
982 AssertIndexRange(inclusion_id, rotated_inclusion_data.size());
983 rotated_inclusion_data[inclusion_id] = rotated_phi;
984 // std::cout << "rotated inclusions data: ";
985 // for (auto i : rotated_inclusion_data[inclusion_id])
986 // std::cout << i << " ";
987 // std::cout << std::endl;
988 }
989 }
990 }
991
998 std::vector<double>
1000 {
1001 AssertIndexRange(inclusion_id, inclusions.size());
1002
1003 // if constexpr (spacedim == 2)
1004 return inclusions_data[inclusion_id];
1005
1006 // if constexpr (spacedim == 3)
1007 return rotated_inclusion_data[inclusion_id];
1008 }
1009
1010 void
1011 set_n_q_points(unsigned int n_q)
1012 {
1013 n_q_points = n_q;
1014 }
1015
1016
1017 void
1019 {
1020 this->n_coefficients = n_coefficients;
1021 }
1022
1023
1026 std::vector<std::vector<double>> inclusions;
1027
1028 std::string data_file = "";
1029#ifdef DEAL_II_WITH_HDF5
1030 mutable std::unique_ptr<HDF5::File> data_file_h;
1031#endif
1032 std::vector<std::vector<double>> inclusions_data;
1033 std::vector<double> reference_inclusion_data;
1034 std::vector<std::vector<double>> rotated_inclusion_data;
1035
1036 std::map<unsigned int, std::vector<types::global_dof_index>>
1038
1039private:
1040 unsigned int n_q_points = 100;
1041 unsigned int n_coefficients = 1;
1042 unsigned int offset_coefficients = 0;
1043 std::vector<unsigned int> selected_coefficients;
1044
1045 const unsigned int n_vector_components;
1047 std::vector<Point<spacedim>> support_points;
1048 std::vector<double> theta;
1049
1050 // Current configuration
1051 mutable std::vector<Tensor<1, spacedim>> normals;
1052 mutable std::vector<Point<spacedim>> current_support_points;
1053 mutable std::vector<double> current_fe_values;
1054
1055 unsigned int n_vessels = 1;
1056
1057 std::string inclusions_file = "";
1058 unsigned int rtree_extraction_level = 1;
1059
1064 void
1066 {
1067 // TODO:
1068 // vessel sanity check: that vessel with same label have the same direction
1069 if (inclusions.size() == 0)
1070 return;
1071
1072 if constexpr (spacedim == 2)
1073 n_vessels = inclusions.size();
1074 {
1075 for (types::global_dof_index inc_number = 0;
1076 inc_number < inclusions.size();
1077 ++inc_number)
1078 map_vessel_inclusions[get_vesselID(inc_number)].push_back(inc_number);
1079
1080 types::global_dof_index id_check = 0;
1081
1082 std::map<unsigned int, std::vector<types::global_dof_index>>::iterator
1083 it = map_vessel_inclusions.begin();
1084
1085 while (it != map_vessel_inclusions.end() && id_check == it->first)
1086 {
1087 ++id_check;
1088 ++it;
1089 }
1091 it == map_vessel_inclusions.end(),
1092 ExcMessage(
1093 "Vessel Ids from data file should be sequential, missing vessels ID(s)"));
1094
1096 }
1097 /*
1098 {
1099 std::set<double> vessel_id_is_present;
1100 for (types::global_dof_index inc_number = 0; inc_number < inclusions.size();
1101 ++inc_number)
1102 vessel_id_is_present.insert(get_vesselID(inc_number));
1103
1104 types::global_dof_index id_check = 0;
1105 while (id_check < vessel_id_is_present.size() &&
1106 vessel_id_is_present.find(id_check) != vessel_id_is_present.end())
1107 ++id_check;
1108
1109 AssertThrow(
1110 id_check + 1 != vessel_id_is_present.size(),
1111 ExcMessage(
1112 "Vessel Ids from data file should be sequential, missing vessels
1113 ID(s)"));
1114 n_vessels = vessel_id_is_present.size();
1115 }
1116 */
1117 }
1118};
1119
1120#endif
void write_vtu_in_parallel(const std::string &filename, const MPI_Comm comm) const
ParameterAcceptor(const std::string &section_name="")
static ParameterHandler prm
void add_parameter(const std::string &entry, ParameterType &parameter, const std::string &documentation="", ParameterHandler &prm_=prm, const Patterns::PatternBase &pattern=*Patterns::Tools::Convert< ParameterType >::to_pattern())
void build_patches(const Particles::ParticleHandler< dim, spacedim > &particles, const std::vector< std::string > &data_component_names={}, const std::vector< DataComponentInterpretation::DataComponentInterpretation > &data_component_interpretations={})
numbers::NumberTraits< Number >::real_type norm() const
void unroll(const Iterator begin, const Iterator end) const
std::vector< unsigned int > selected_coefficients
unsigned int get_fourier_component(const types::global_dof_index &dof_index) const
Get the ith Fourier component for the given dof index.
Definition inclusions.h:382
std::vector< Tensor< 1, spacedim > > normals
double get_JxW(const types::global_dof_index &particle_id) const
return weight for integration normal direction of an inclusion at a quadrature point
Definition inclusions.h:475
unsigned int n_dofs_per_inclusion() const
Number of degrees of freedom associated to each inclusion.
Definition inclusions.h:158
std::string data_file
std::vector< double > theta
double get_inclusion_data(const types::global_dof_index &inclusion_id, const types::global_dof_index &dof_index) const
Get the Fourier data for the given local dof index.
Definition inclusions.h:398
void set_n_coefficients(unsigned int n_coefficients)
unsigned int get_n_coefficients() const
Definition inclusions.h:921
void output_particles(const std::string &filename) const
print the inclusions in parallel on a .vtu file
Definition inclusions.h:702
std::map< unsigned int, std::vector< types::global_dof_index > > map_vessel_inclusions
unsigned int rtree_extraction_level
std::vector< double > current_fe_values
unsigned int n_q_points
Inclusions(const unsigned int n_vector_components=1)
Class for computing the inclusions of a given mesh.
Definition inclusions.h:75
void update_inclusions_data(std::vector< std::vector< double > > new_data)
Definition inclusions.h:795
unsigned int get_component(const types::global_dof_index &dof_index) const
Get the ith component for the given dof index.
Definition inclusions.h:366
const unsigned int n_vector_components
const std::vector< double > & get_fe_values(const types::global_dof_index particle_id) const
Definition inclusions.h:492
types::global_dof_index get_inclusion_id(const types::global_dof_index &quadrature_id) const
Definition inclusions.h:353
unsigned int n_coefficients
void update_inclusions_data(std::vector< double > new_data)
Update the displacement data after the initialization, 3D case only.
Definition inclusions.h:759
double get_section_measure(const types::global_dof_index &inclusion_id) const
Get the measure of the section of the inclusion.
Definition inclusions.h:593
std::vector< std::vector< double > > inclusions
std::vector< std::vector< double > > rotated_inclusion_data
std::vector< double > reference_inclusion_data
types::global_dof_index n_inclusions() const
Returns the number of inclusions in the mesh.
Definition inclusions.h:147
std::vector< types::global_dof_index > get_dof_indices(const types::global_dof_index &quadrature_id) const
Returns the degrees of freedom indices associated with a given quadrature point.
Definition inclusions.h:277
std::vector< double > get_rotated_inclusion_data(const types::global_dof_index &inclusion_id) const
return the rotate the data of a given inclusion
Definition inclusions.h:999
unsigned int get_n_vessels() const
Definition inclusions.h:915
void set_n_q_points(unsigned int n_q)
void compute_rotated_inclusion_data()
Definition inclusions.h:941
std::vector< Point< spacedim > > current_support_points
std::vector< Point< spacedim > > support_points
void check_vessels()
Check that all vesselsID are present and create the map vessel_inclusions.
std::vector< std::vector< double > > inclusions_data
unsigned int get_inclusions_in_vessel(unsigned int vessel_id) const
Definition inclusions.h:933
unsigned int offset_coefficients
Tensor< 1, spacedim > get_direction(const types::global_dof_index &inclusion_id) const
Get the direction of the inclusion.
Definition inclusions.h:613
types::global_dof_index n_particles() const
Definition inclusions.h:135
unsigned int get_offset_coefficients() const
Definition inclusions.h:927
int get_vesselID(const types::global_dof_index &inclusion_id) const
3D return the vessel that a given inclusion belongs to, 2D return 0
Definition inclusions.h:871
double get_inclusion_data(const types::global_dof_index &inclusion_id, const types::global_dof_index &dof_index, const Point< spacedim > &point) const
Get the Fourier data for the given local dof index.
Definition inclusions.h:417
friend class CouplingOperator
Definition inclusions.h:68
const Tensor< 1, spacedim > & get_normal(const types::global_dof_index &quadrature_id) const
Get the normal.
Definition inclusions.h:455
Point< spacedim > get_center(const types::global_dof_index &inclusion_id) const
Get the center of the inclusion.
Definition inclusions.h:551
MPI_Comm mpi_communicator
ParameterAcceptorProxy< Functions::ParsedFunction< spacedim > > inclusions_rhs
Particles::ParticleHandler< spacedim > inclusions_as_particles
void update_displacement_hdf5()
Update the displacement data after the initialization reading from a hdf5 file.
Definition inclusions.h:713
void setup_inclusions_particles(const parallel::distributed::Triangulation< spacedim > &tria)
Sets up the inclusions particles for the given triangulation.
Definition inclusions.h:293
std::string inclusions_file
void update_single_inclusion_data_along_normal(const types::global_dof_index &inclusion_id, const double nd)
Definition inclusions.h:887
double get_radius(const types::global_dof_index &inclusion_id) const
Get the radius of the inclusion.
Definition inclusions.h:570
unsigned int n_vessels
const std::vector< Point< spacedim > > & get_current_support_points(const types::global_dof_index &inclusion_id) const
Definition inclusions.h:683
void update_single_vessel_data(const types::global_dof_index &, const std::vector< double >)
Definition inclusions.h:910
void initialize()
Definition inclusions.h:168
Tensor< 2, spacedim > get_rotation(const types::global_dof_index &inclusion_id) const
Get the rotation of the inclusion.
Definition inclusions.h:644
types::global_dof_index n_dofs() const
Definition inclusions.h:123
unsigned int n_locally_owned_active_cells() const
IteratorRange< active_cell_iterator > active_cell_iterators() const
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
#define AssertThrow(cond, exc)
std::size_t size
Expression floor(const Expression &x)
Tensor< 2, dim, Number > w(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
std::vector< T > all_gather(const MPI_Comm comm, const T &object_to_send)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
IndexSet create_evenly_distributed_partitioning(const MPI_Comm comm, const types::global_dof_index total_size)
constexpr double PI
::VectorizedArray< Number, width > cos(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sin(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
unsigned int global_dof_index
std::vector< BoundingBox< boost::geometry::dimension< typename Rtree::indexable_type >::value > > extract_rtree_level(const Rtree &tree, const unsigned int level)
RTree< typename LeafTypeIterator::value_type, IndexType, IndexableGetter > pack_rtree(const LeafTypeIterator &begin, const LeafTypeIterator &end)
static MappingQ< dim, spacedim > mapping
DEAL_II_HOST constexpr SymmetricTensor< 2, dim, Number > unit_symmetric_tensor()