OGS
ComponentTransportFEM.h
Go to the documentation of this file.
1
11#pragma once
12
13#include <numeric>
14#include <vector>
15
36
37namespace ProcessLib
38{
39namespace ComponentTransport
40{
41template <typename GlobalDimNodalMatrixType>
43{
44 IntegrationPointData(GlobalDimNodalMatrixType const& dNdx_,
45 double const& integration_weight_)
46 : dNdx(dNdx_), integration_weight(integration_weight_)
47 {
48 }
49
51 GlobalDimNodalMatrixType const dNdx;
52 double const integration_weight;
53
54 // -1 indicates that no chemical reaction takes place in the element to
55 // which the integration point belongs.
57
58 double porosity = std::numeric_limits<double>::quiet_NaN();
59 double porosity_prev = std::numeric_limits<double>::quiet_NaN();
61};
62
66{
67public:
69
70 virtual void setChemicalSystemID(std::size_t const /*mesh_item_id*/) = 0;
71
73 std::size_t const mesh_item_id,
74 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_tables,
75 std::vector<GlobalVector*> const& x, double const t)
76 {
77 std::vector<double> local_x_vec;
78
79 auto const n_processes = x.size();
80 for (std::size_t process_id = 0; process_id < n_processes; ++process_id)
81 {
82 auto const indices =
83 NumLib::getIndices(mesh_item_id, *dof_tables[process_id]);
84 assert(!indices.empty());
85 auto const local_solution = x[process_id]->get(indices);
86 local_x_vec.insert(std::end(local_x_vec),
87 std::begin(local_solution),
88 std::end(local_solution));
89 }
90 auto const local_x = MathLib::toVector(local_x_vec);
91
93 }
94
96 std::size_t const mesh_item_id,
97 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_tables,
98 std::vector<GlobalVector*> const& x, double const t, double const dt)
99 {
100 std::vector<double> local_x_vec;
101
102 auto const n_processes = x.size();
103 for (std::size_t process_id = 0; process_id < n_processes; ++process_id)
104 {
105 auto const indices =
106 NumLib::getIndices(mesh_item_id, *dof_tables[process_id]);
107 assert(!indices.empty());
108 auto const local_solution = x[process_id]->get(indices);
109 local_x_vec.insert(std::end(local_x_vec),
110 std::begin(local_solution),
111 std::end(local_solution));
112 }
113 auto const local_x = MathLib::toVector(local_x_vec);
114
115 setChemicalSystemConcrete(local_x, t, dt);
116 }
117
119 std::size_t const mesh_item_id,
120 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_tables,
121 std::vector<GlobalVector*> const& x, double const t, double const dt,
122 GlobalMatrix& M, GlobalMatrix& K, GlobalVector& b, int const process_id)
123 {
124 std::vector<double> local_x_vec;
125
126 auto const n_processes = x.size();
127 for (std::size_t pcs_id = 0; pcs_id < n_processes; ++pcs_id)
128 {
129 auto const indices =
130 NumLib::getIndices(mesh_item_id, *dof_tables[pcs_id]);
131 assert(!indices.empty());
132 auto const local_solution = x[pcs_id]->get(indices);
133 local_x_vec.insert(std::end(local_x_vec),
134 std::begin(local_solution),
135 std::end(local_solution));
136 }
137 auto const local_x = MathLib::toVector(local_x_vec);
138
139 auto const indices =
140 NumLib::getIndices(mesh_item_id, *dof_tables[process_id]);
141 auto const num_r_c = indices.size();
142
143 std::vector<double> local_M_data;
144 local_M_data.reserve(num_r_c * num_r_c);
145 std::vector<double> local_K_data;
146 local_K_data.reserve(num_r_c * num_r_c);
147 std::vector<double> local_b_data;
148 local_b_data.reserve(num_r_c);
149
150 assembleReactionEquationConcrete(t, dt, local_x, local_M_data,
151 local_K_data, local_b_data,
152 process_id);
153
154 auto const r_c_indices =
156 if (!local_M_data.empty())
157 {
158 auto const local_M =
159 MathLib::toMatrix(local_M_data, num_r_c, num_r_c);
160 M.add(r_c_indices, local_M);
161 }
162 if (!local_K_data.empty())
163 {
164 auto const local_K =
165 MathLib::toMatrix(local_K_data, num_r_c, num_r_c);
166 K.add(r_c_indices, local_K);
167 }
168 if (!local_b_data.empty())
169 {
170 b.add(indices, local_b_data);
171 }
172 }
173
174 virtual void postSpeciationCalculation(std::size_t const ele_id,
175 double const t, double const dt) = 0;
176
178 std::size_t const ele_id) = 0;
179
180 virtual std::vector<double> const& getIntPtDarcyVelocity(
181 const double t,
182 std::vector<GlobalVector*> const& x,
183 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_table,
184 std::vector<double>& cache) const = 0;
185
186 virtual std::vector<double> const& getIntPtMolarFlux(
187 const double t, std::vector<GlobalVector*> const& x,
188 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_table,
189 std::vector<double>& cache, int const component_id) const = 0;
190
191private:
193 Eigen::VectorXd const& /*local_x*/, double const /*t*/) = 0;
194
195 virtual void setChemicalSystemConcrete(Eigen::VectorXd const& /*local_x*/,
196 double const /*t*/,
197 double const /*dt*/) = 0;
198
200 double const t, double const dt, Eigen::VectorXd const& local_x,
201 std::vector<double>& local_M_data, std::vector<double>& local_K_data,
202 std::vector<double>& local_b_data, int const transport_process_id) = 0;
203};
204
205template <typename ShapeFunction, int GlobalDim>
207{
208 // When monolithic scheme is adopted, nodal pressure and nodal concentration
209 // are accessed by vector index.
210 static const int pressure_index = 0;
211 const int temperature_index = -1;
213
214 static const int pressure_size = ShapeFunction::NPOINTS;
215 static const int temperature_size = ShapeFunction::NPOINTS;
216 static const int concentration_size =
217 ShapeFunction::NPOINTS; // per component
218
221
223 typename ShapeMatricesType::template MatrixType<pressure_size,
226 typename ShapeMatricesType::template VectorType<pressure_size>;
227
229 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
230 using LocalVectorType = Eigen::Matrix<double, Eigen::Dynamic, 1>;
231
234
239
240public:
242 MeshLib::Element const& element,
243 std::size_t const local_matrix_size,
244 NumLib::GenericIntegrationMethod const& integration_method,
245 bool is_axially_symmetric,
246 ComponentTransportProcessData const& process_data,
247 std::vector<std::reference_wrapper<ProcessVariable>> const&
248 transport_process_variables)
249 : temperature_index(process_data.isothermal ? -1
250 : ShapeFunction::NPOINTS),
251 first_concentration_index(process_data.isothermal
252 ? ShapeFunction::NPOINTS
253 : 2 * ShapeFunction::NPOINTS),
254 _element(element),
255 _process_data(process_data),
256 _integration_method(integration_method),
257 _transport_process_variables(transport_process_variables)
258 {
259 (void)local_matrix_size;
260
261 unsigned const n_integration_points =
263 _ip_data.reserve(n_integration_points);
264
267
268 double const aperture_size = _process_data.aperture_size(0.0, pos)[0];
269
270 auto const shape_matrices =
272 GlobalDim>(element, is_axially_symmetric,
274 auto const& medium =
276 for (unsigned ip = 0; ip < n_integration_points; ip++)
277 {
278 _ip_data.emplace_back(
279 shape_matrices[ip].dNdx,
281 shape_matrices[ip].integralMeasure *
282 shape_matrices[ip].detJ * aperture_size);
283
284 _ip_data[ip].porosity =
286 .template initialValue<double>(
287 pos, std::numeric_limits<double>::quiet_NaN() /*t*/);
288
289 _ip_data[ip].pushBackState();
290 }
291 }
292
293 void setChemicalSystemID(std::size_t const /*mesh_item_id*/) override
294 {
296 // chemical system index map
297 auto& chemical_system_index_map =
299
300 unsigned const n_integration_points =
302 for (unsigned ip = 0; ip < n_integration_points; ip++)
303 {
304 _ip_data[ip].chemical_system_id =
305 chemical_system_index_map.empty()
306 ? 0
307 : chemical_system_index_map.back() + 1;
308 chemical_system_index_map.push_back(
309 _ip_data[ip].chemical_system_id);
310 }
311 }
312
313 void initializeChemicalSystemConcrete(Eigen::VectorXd const& local_x,
314 double const t) override
315 {
317
318 auto const& medium =
320
323
324 auto const& Ns =
326 .NsHigherOrder<typename ShapeFunction::MeshElement>();
327
328 unsigned const n_integration_points =
330
331 for (unsigned ip = 0; ip < n_integration_points; ip++)
332 {
333 auto& ip_data = _ip_data[ip];
334 auto const& N = Ns[ip];
335 auto const& chemical_system_id = ip_data.chemical_system_id;
336
337 // set position with N as the shape matrix at the current
338 // integration point
342 N)));
343
344 auto const n_component = _transport_process_variables.size();
345 std::vector<double> C_int_pt(n_component);
346 for (unsigned component_id = 0; component_id < n_component;
347 ++component_id)
348 {
349 auto const concentration_index =
351 component_id * concentration_size;
352 auto const local_C =
353 local_x.template segment<concentration_size>(
354 concentration_index);
355
357 C_int_pt[component_id]);
358 }
359
361 ->initializeChemicalSystemConcrete(C_int_pt, chemical_system_id,
362 medium, pos, t);
363 }
364 }
365
366 void setChemicalSystemConcrete(Eigen::VectorXd const& local_x,
367 double const t, double dt) override
368 {
370
371 auto const& medium =
373
376
379
380 auto const& Ns =
382 .NsHigherOrder<typename ShapeFunction::MeshElement>();
383
384 unsigned const n_integration_points =
386
387 for (unsigned ip = 0; ip < n_integration_points; ip++)
388 {
389 auto& ip_data = _ip_data[ip];
390 auto const& N = Ns[ip];
391 auto& porosity = ip_data.porosity;
392 auto const& porosity_prev = ip_data.porosity_prev;
393 auto const& chemical_system_id = ip_data.chemical_system_id;
394
395 auto const n_component = _transport_process_variables.size();
396 std::vector<double> C_int_pt(n_component);
397 for (unsigned component_id = 0; component_id < n_component;
398 ++component_id)
399 {
400 auto const concentration_index =
402 component_id * concentration_size;
403 auto const local_C =
404 local_x.template segment<concentration_size>(
405 concentration_index);
406
408 C_int_pt[component_id]);
409 }
410
411 {
412 vars_prev.porosity = porosity_prev;
413
414 porosity =
416 ? porosity_prev
417 : medium
418 ->property(
420 .template value<double>(vars, vars_prev, pos, t,
421 dt);
422
423 vars.porosity = porosity;
424 }
425
427 C_int_pt, chemical_system_id, medium, vars, pos, t, dt);
428 }
429 }
430
431 void postSpeciationCalculation(std::size_t const ele_id, double const t,
432 double const dt) override
433 {
435 {
436 return;
437 }
438
439 auto const& medium = *_process_data.media_map.getMedium(ele_id);
440
442 pos.setElementID(ele_id);
443
444 for (auto& ip_data : _ip_data)
445 {
446 ip_data.porosity = ip_data.porosity_prev;
447
449 ->updateVolumeFractionPostReaction(ip_data.chemical_system_id,
450 medium, pos,
451 ip_data.porosity, t, dt);
452
454 ip_data.chemical_system_id, medium, ip_data.porosity);
455 }
456 }
457
458 void assemble(double const t, double const dt,
459 std::vector<double> const& local_x,
460 std::vector<double> const& /*local_x_prev*/,
461 std::vector<double>& local_M_data,
462 std::vector<double>& local_K_data,
463 std::vector<double>& local_b_data) override
464 {
465 auto const local_matrix_size = local_x.size();
466 // Nodal DOFs include pressure
467 int const num_nodal_dof = 1 + _transport_process_variables.size();
468 // This assertion is valid only if all nodal d.o.f. use the same shape
469 // matrices.
470 assert(local_matrix_size == ShapeFunction::NPOINTS * num_nodal_dof);
471
473 local_M_data, local_matrix_size, local_matrix_size);
475 local_K_data, local_matrix_size, local_matrix_size);
477 local_b_data, local_matrix_size);
478
479 // Get block matrices
480 auto Kpp = local_K.template block<pressure_size, pressure_size>(
482 auto Mpp = local_M.template block<pressure_size, pressure_size>(
484 auto Bp = local_b.template segment<pressure_size>(pressure_index);
485
486 auto local_p = Eigen::Map<const NodalVectorType>(
487 &local_x[pressure_index], pressure_size);
488
489 auto const& b =
492
493 auto const number_of_components = num_nodal_dof - 1;
494 for (int component_id = 0; component_id < number_of_components;
495 ++component_id)
496 {
497 /* Partitioned assembler matrix
498 * | pp | pc1 | pc2 | pc3 |
499 * |-----|-----|-----|-----|
500 * | c1p | c1c1| 0 | 0 |
501 * |-----|-----|-----|-----|
502 * | c2p | 0 | c2c2| 0 |
503 * |-----|-----|-----|-----|
504 * | c3p | 0 | 0 | c3c3|
505 */
506 auto concentration_index =
507 pressure_size + component_id * concentration_size;
508
509 auto KCC =
510 local_K.template block<concentration_size, concentration_size>(
511 concentration_index, concentration_index);
512 auto MCC =
513 local_M.template block<concentration_size, concentration_size>(
514 concentration_index, concentration_index);
515 auto MCp =
516 local_M.template block<concentration_size, pressure_size>(
517 concentration_index, pressure_index);
518 auto MpC =
519 local_M.template block<pressure_size, concentration_size>(
520 pressure_index, concentration_index);
521
522 auto local_C = Eigen::Map<const NodalVectorType>(
523 &local_x[concentration_index], concentration_size);
524
525 assembleBlockMatrices(b, component_id, t, dt, local_C, local_p, KCC,
526 MCC, MCp, MpC, Kpp, Mpp, Bp);
527
529 {
530 auto const stoichiometric_matrix =
533
534 assert(stoichiometric_matrix);
535
536 for (Eigen::SparseMatrix<double>::InnerIterator it(
537 *stoichiometric_matrix, component_id);
538 it;
539 ++it)
540 {
541 auto const stoichiometric_coefficient = it.value();
542 auto const coupled_component_id = it.row();
543 auto const kinetic_prefactor =
545 ->getKineticPrefactor(coupled_component_id);
546
547 auto const concentration_index =
548 pressure_size + component_id * concentration_size;
549 auto const coupled_concentration_index =
551 coupled_component_id * concentration_size;
552 auto KCmCn = local_K.template block<concentration_size,
554 concentration_index, coupled_concentration_index);
555
556 // account for the coupling between components
557 assembleKCmCn(component_id, t, dt, KCmCn,
558 stoichiometric_coefficient,
559 kinetic_prefactor);
560 }
561 }
562 }
563 }
564
566 GlobalDimVectorType const& b, int const component_id, double const t,
567 double const dt,
568 Eigen::Ref<const NodalVectorType> const& C_nodal_values,
569 Eigen::Ref<const NodalVectorType> const& p_nodal_values,
570 Eigen::Ref<LocalBlockMatrixType> KCC,
571 Eigen::Ref<LocalBlockMatrixType> MCC,
572 Eigen::Ref<LocalBlockMatrixType> MCp,
573 Eigen::Ref<LocalBlockMatrixType> MpC,
574 Eigen::Ref<LocalBlockMatrixType> Kpp,
575 Eigen::Ref<LocalBlockMatrixType> Mpp,
576 Eigen::Ref<LocalSegmentVectorType> Bp)
577 {
578 unsigned const n_integration_points =
580
583
585
586 // Get material properties
587 auto const& medium =
589 // Select the only valid for component transport liquid phase.
590 auto const& phase = medium.phase("AqueousLiquid");
591
592 // Assume that the component name is the same as the process variable
593 // name. Components are shifted by one because the first one is always
594 // pressure.
595 auto const& component = phase.component(
596 _transport_process_variables[component_id].get().getName());
597
598 LocalBlockMatrixType KCC_Laplacian =
599 LocalBlockMatrixType::Zero(concentration_size, concentration_size);
600
601 std::vector<GlobalDimVectorType> ip_flux_vector;
602 double average_velocity_norm = 0.0;
604 {
605 ip_flux_vector.reserve(n_integration_points);
606 }
607
608 auto const& Ns =
610 .NsHigherOrder<typename ShapeFunction::MeshElement>();
611
612 for (unsigned ip(0); ip < n_integration_points; ++ip)
613 {
614 auto& ip_data = _ip_data[ip];
615 auto const& dNdx = ip_data.dNdx;
616 auto const& N = Ns[ip];
617 auto const& w = ip_data.integration_weight;
618 auto& porosity = ip_data.porosity;
619
620 double C_int_pt = 0.0;
621 double p_int_pt = 0.0;
622
623 NumLib::shapeFunctionInterpolate(C_nodal_values, N, C_int_pt);
624 NumLib::shapeFunctionInterpolate(p_nodal_values, N, p_int_pt);
625
626 // set position with N as the shape matrix at the current
627 // integration point
631 N)));
632
633 vars.concentration = C_int_pt;
634 vars.liquid_phase_pressure = p_int_pt;
635
636 // update according to a particular porosity model
638 .template value<double>(vars, pos, t, dt);
639 vars.porosity = porosity;
640
641 auto const& retardation_factor =
643 .template value<double>(vars, pos, t, dt);
644
645 auto const& solute_dispersivity_transverse = medium.template value<
646 double>(
648
649 auto const& solute_dispersivity_longitudinal =
650 medium.template value<double>(
652 longitudinal_dispersivity);
653
654 // Use the fluid density model to compute the density
655 // TODO (renchao): concentration of which component as the argument
656 // for calculation of fluid density
657 auto const density =
659 .template value<double>(vars, pos, t, dt);
660
661 auto const decay_rate =
663 .template value<double>(vars, pos, t, dt);
664
665 auto const& pore_diffusion_coefficient =
668 .value(vars, pos, t, dt));
669
672 vars, pos, t, dt));
673
674 // Use the viscosity model to compute the viscosity
676 .template value<double>(vars, pos, t, dt);
677
678 GlobalDimMatrixType const K_over_mu = K / mu;
679 GlobalDimVectorType const velocity =
681 ? GlobalDimVectorType(-K_over_mu *
682 (dNdx * p_nodal_values - density * b))
683 : GlobalDimVectorType(-K_over_mu * dNdx * p_nodal_values);
684
685 const double drho_dp =
687 .template dValue<double>(
688 vars,
690 pos, t, dt);
691
692 const double drho_dC =
694 .template dValue<double>(
696 t, dt);
697
698 GlobalDimMatrixType const hydrodynamic_dispersion =
701 pore_diffusion_coefficient, velocity, porosity,
702 solute_dispersivity_transverse,
703 solute_dispersivity_longitudinal);
704
705 const double R_times_phi(retardation_factor * porosity);
706 GlobalDimVectorType const mass_density_flow = velocity * density;
707 auto const N_t_N = (N.transpose() * N).eval();
708
710 {
711 MCp.noalias() += N_t_N * (C_int_pt * R_times_phi * drho_dp * w);
712 MCC.noalias() += N_t_N * (C_int_pt * R_times_phi * drho_dC * w);
713 KCC.noalias() -= dNdx.transpose() * mass_density_flow * N * w;
714 }
715 else
716 {
717 ip_flux_vector.emplace_back(mass_density_flow);
718 average_velocity_norm += velocity.norm();
719 }
720 MCC.noalias() += N_t_N * (R_times_phi * density * w);
721 KCC.noalias() += N_t_N * (decay_rate * R_times_phi * density * w);
722 KCC_Laplacian.noalias() +=
723 dNdx.transpose() * hydrodynamic_dispersion * dNdx * density * w;
724
725 MpC.noalias() += N_t_N * (porosity * drho_dC * w);
726
727 // Calculate Mpp, Kpp, and bp in the first loop over components
728 if (component_id == 0)
729 {
730 Mpp.noalias() += N_t_N * (porosity * drho_dp * w);
731 Kpp.noalias() +=
732 dNdx.transpose() * K_over_mu * dNdx * (density * w);
733
735 {
736 Bp.noalias() += dNdx.transpose() * K_over_mu * b *
737 (density * density * w);
738 }
739 }
740 }
741
743 {
745 typename ShapeFunction::MeshElement>(
747 _ip_data,
749 ip_flux_vector,
750 average_velocity_norm /
751 static_cast<double>(n_integration_points),
752 KCC_Laplacian);
753 }
754
755 KCC.noalias() += KCC_Laplacian;
756 }
757
758 void assembleKCmCn(int const component_id, double const t, double const dt,
759 Eigen::Ref<LocalBlockMatrixType> KCmCn,
760 double const stoichiometric_coefficient,
761 double const kinetic_prefactor)
762 {
763 unsigned const n_integration_points =
765
768
770
771 auto const& medium =
773 auto const& phase = medium.phase("AqueousLiquid");
774 auto const& component = phase.component(
775 _transport_process_variables[component_id].get().getName());
776
777 auto const& Ns =
779 .NsHigherOrder<typename ShapeFunction::MeshElement>();
780
781 for (unsigned ip(0); ip < n_integration_points; ++ip)
782 {
783 auto& ip_data = _ip_data[ip];
784 auto const& w = ip_data.integration_weight;
785 auto const& N = Ns[ip];
786 auto& porosity = ip_data.porosity;
787
788 // set position with N as the shape matrix at the current
789 // integration point
793 N)));
794
795 auto const retardation_factor =
797 .template value<double>(vars, pos, t, dt);
798
800 .template value<double>(vars, pos, t, dt);
801
802 auto const density =
804 .template value<double>(vars, pos, t, dt);
805
806 KCmCn.noalias() -= w * N.transpose() * stoichiometric_coefficient *
807 kinetic_prefactor * retardation_factor *
808 porosity * density * N;
809 }
810 }
811
812 void assembleForStaggeredScheme(double const t, double const dt,
813 Eigen::VectorXd const& local_x,
814 Eigen::VectorXd const& local_x_prev,
815 int const process_id,
816 std::vector<double>& local_M_data,
817 std::vector<double>& local_K_data,
818 std::vector<double>& local_b_data) override
819 {
820 if (process_id == _process_data.hydraulic_process_id)
821 {
822 assembleHydraulicEquation(t, dt, local_x, local_x_prev,
823 local_M_data, local_K_data, local_b_data);
824 }
825 else if (process_id == _process_data.thermal_process_id)
826 {
827 assembleHeatTransportEquation(t, dt, local_x, local_x_prev,
828 local_M_data, local_K_data,
829 local_b_data);
830 }
831 else
832 {
833 // Go for assembling in an order of transport process id.
834 assembleComponentTransportEquation(t, dt, local_x, local_x_prev,
835 local_M_data, local_K_data,
836 local_b_data, process_id);
837 }
838 }
839
840 void assembleHydraulicEquation(double const t,
841 double const dt,
842 Eigen::VectorXd const& local_x,
843 Eigen::VectorXd const& local_x_prev,
844 std::vector<double>& local_M_data,
845 std::vector<double>& local_K_data,
846 std::vector<double>& local_b_data)
847 {
848 auto const local_p =
849 local_x.template segment<pressure_size>(pressure_index);
850 auto const local_C = local_x.template segment<concentration_size>(
852 auto const local_C_prev =
853 local_x_prev.segment<concentration_size>(first_concentration_index);
854
855 NodalVectorType local_T = getLocalTemperature(t, local_x);
856
858 local_M_data, pressure_size, pressure_size);
860 local_K_data, pressure_size, pressure_size);
862 local_b_data, pressure_size);
863
864 unsigned const n_integration_points =
866
869
870 auto const& b =
873
874 auto const& medium =
876 auto const& phase = medium.phase("AqueousLiquid");
877
880
881 auto const& Ns =
883 .NsHigherOrder<typename ShapeFunction::MeshElement>();
884
885 for (unsigned ip(0); ip < n_integration_points; ++ip)
886 {
887 auto& ip_data = _ip_data[ip];
888 auto const& dNdx = ip_data.dNdx;
889 auto const& w = ip_data.integration_weight;
890 auto const& N = Ns[ip];
891 auto& porosity = ip_data.porosity;
892 auto const& porosity_prev = ip_data.porosity_prev;
893
894 double const C_int_pt = N.dot(local_C);
895 double const p_int_pt = N.dot(local_p);
896 double const T_int_pt = N.dot(local_T);
897
898 vars.concentration = C_int_pt;
899 vars.liquid_phase_pressure = p_int_pt;
900 vars.temperature = T_int_pt;
901
902 // porosity
903 {
904 vars_prev.porosity = porosity_prev;
905
906 porosity =
908 ? porosity_prev
910 .template value<double>(vars, vars_prev, pos, t,
911 dt);
912
913 vars.porosity = porosity;
914 }
915
916 // Use the fluid density model to compute the density
917 // TODO: Concentration of which component as one of arguments for
918 // calculation of fluid density
919 auto const density =
921 .template value<double>(vars, pos, t, dt);
922
925 vars, pos, t, dt));
926
927 // Use the viscosity model to compute the viscosity
929 .template value<double>(vars, pos, t, dt);
930
931 GlobalDimMatrixType const K_over_mu = K / mu;
932
933 const double drho_dp =
935 .template dValue<double>(
936 vars,
938 pos, t, dt);
939 const double drho_dC =
941 .template dValue<double>(
943 t, dt);
944
945 // matrix assembly
946 local_M.noalias() += w * N.transpose() * porosity * drho_dp * N;
947 local_K.noalias() +=
948 w * dNdx.transpose() * density * K_over_mu * dNdx;
949
951 {
952 local_b.noalias() +=
953 w * density * density * dNdx.transpose() * K_over_mu * b;
954 }
955
956 // coupling term
957 {
958 double const C_dot = (C_int_pt - N.dot(local_C_prev)) / dt;
959
960 local_b.noalias() -=
961 w * N.transpose() * porosity * drho_dC * C_dot;
962 }
963 }
964 }
965
966 void assembleHeatTransportEquation(double const t, double const dt,
967 Eigen::VectorXd const& local_x,
968 Eigen::VectorXd const& /*local_x_prev*/,
969 std::vector<double>& local_M_data,
970 std::vector<double>& local_K_data,
971 std::vector<double>& /*local_b_data*/)
972 {
973 assert(local_x.size() ==
975
976 auto const local_p =
977 local_x.template segment<pressure_size>(pressure_index);
978 auto const local_T = getLocalTemperature(t, local_x);
979
981 local_M_data, temperature_size, temperature_size);
983 local_K_data, temperature_size, temperature_size);
984
986 pos.setElementID(this->_element.getID());
987
988 auto const& process_data = this->_process_data;
989 auto const& medium =
990 *process_data.media_map.getMedium(this->_element.getID());
991 auto const& liquid_phase = medium.phase("AqueousLiquid");
992
993 auto const& b =
996
998
999 unsigned const n_integration_points =
1001
1002 std::vector<GlobalDimVectorType> ip_flux_vector;
1003 double average_velocity_norm = 0.0;
1004 ip_flux_vector.reserve(n_integration_points);
1005
1006 auto const& Ns =
1008 .NsHigherOrder<typename ShapeFunction::MeshElement>();
1009
1010 for (unsigned ip(0); ip < n_integration_points; ip++)
1011 {
1012 auto const& ip_data = this->_ip_data[ip];
1013 auto const& dNdx = ip_data.dNdx;
1014 auto const& w = ip_data.integration_weight;
1015 auto const& N = Ns[ip];
1016
1017 double p_at_xi = 0.;
1018 NumLib::shapeFunctionInterpolate(local_p, N, p_at_xi);
1019 double T_at_xi = 0.;
1020 NumLib::shapeFunctionInterpolate(local_T, N, T_at_xi);
1021
1022 vars.temperature = T_at_xi;
1023 vars.liquid_phase_pressure = p_at_xi;
1024
1025 vars.liquid_saturation = 1.0;
1026
1027 auto const porosity =
1029 .template value<double>(vars, pos, t, dt);
1030 vars.porosity = porosity;
1031
1032 // Use the fluid density model to compute the density
1033 auto const fluid_density =
1034 liquid_phase
1036 .template value<double>(vars, pos, t, dt);
1037 vars.density = fluid_density;
1038 auto const specific_heat_capacity_fluid =
1039 liquid_phase
1041 .template value<double>(vars, pos, t, dt);
1042
1043 // Assemble mass matrix
1044 local_M.noalias() += w *
1046 vars, porosity, fluid_density,
1047 specific_heat_capacity_fluid, pos, t, dt) *
1048 N.transpose() * N;
1049
1050 // Assemble Laplace matrix
1051 auto const viscosity =
1052 liquid_phase
1054 .template value<double>(vars, pos, t, dt);
1055
1056 auto const intrinsic_permeability =
1058 medium
1059 .property(
1061 .value(vars, pos, t, dt));
1062
1063 GlobalDimMatrixType const K_over_mu =
1064 intrinsic_permeability / viscosity;
1065 GlobalDimVectorType const velocity =
1066 process_data.has_gravity
1067 ? GlobalDimVectorType(-K_over_mu *
1068 (dNdx * local_p - fluid_density * b))
1069 : GlobalDimVectorType(-K_over_mu * dNdx * local_p);
1070
1071 GlobalDimMatrixType const thermal_conductivity_dispersivity =
1073 vars, fluid_density, specific_heat_capacity_fluid, velocity,
1074 pos, t, dt);
1075
1076 local_K.noalias() +=
1077 w * dNdx.transpose() * thermal_conductivity_dispersivity * dNdx;
1078
1079 ip_flux_vector.emplace_back(velocity * fluid_density *
1080 specific_heat_capacity_fluid);
1081 average_velocity_norm += velocity.norm();
1082 }
1083
1085 process_data.stabilizer, this->_ip_data,
1086 _process_data.shape_matrix_cache, ip_flux_vector,
1087 average_velocity_norm / static_cast<double>(n_integration_points),
1088 local_K);
1089 }
1090
1092 double const t, double const dt, Eigen::VectorXd const& local_x,
1093 Eigen::VectorXd const& local_x_prev, std::vector<double>& local_M_data,
1094 std::vector<double>& local_K_data,
1095 std::vector<double>& /*local_b_data*/, int const transport_process_id)
1096 {
1097 assert(static_cast<int>(local_x.size()) ==
1100 static_cast<int>(_transport_process_variables.size()) +
1102
1103 auto const local_p =
1104 local_x.template segment<pressure_size>(pressure_index);
1105
1106 NodalVectorType local_T = getLocalTemperature(t, local_x);
1107
1108 auto const local_C = local_x.template segment<concentration_size>(
1110 (transport_process_id - (_process_data.isothermal ? 1 : 2)) *
1112 auto const local_p_prev =
1113 local_x_prev.segment<pressure_size>(pressure_index);
1114
1116 local_M_data, concentration_size, concentration_size);
1118 local_K_data, concentration_size, concentration_size);
1119
1120 LocalBlockMatrixType KCC_Laplacian =
1121 LocalBlockMatrixType::Zero(concentration_size, concentration_size);
1122
1123 unsigned const n_integration_points =
1125
1126 std::vector<GlobalDimVectorType> ip_flux_vector;
1127 double average_velocity_norm = 0.0;
1129 {
1130 ip_flux_vector.reserve(n_integration_points);
1131 }
1132
1135
1136 auto const& b =
1139
1142
1143 auto const& medium =
1145 auto const& phase = medium.phase("AqueousLiquid");
1146 auto const component_id =
1147 transport_process_id - (_process_data.isothermal ? 1 : 2);
1148 auto const& component = phase.component(
1149 _transport_process_variables[component_id].get().getName());
1150
1151 auto const& Ns =
1153 .NsHigherOrder<typename ShapeFunction::MeshElement>();
1154
1155 for (unsigned ip(0); ip < n_integration_points; ++ip)
1156 {
1157 auto& ip_data = _ip_data[ip];
1158 auto const& dNdx = ip_data.dNdx;
1159 auto const& w = ip_data.integration_weight;
1160 auto const& N = Ns[ip];
1161 auto& porosity = ip_data.porosity;
1162 auto const& porosity_prev = ip_data.porosity_prev;
1163
1164 double const C_int_pt = N.dot(local_C);
1165 double const p_int_pt = N.dot(local_p);
1166 double const T_int_pt = N.dot(local_T);
1167
1168 vars.concentration = C_int_pt;
1169 vars.liquid_phase_pressure = p_int_pt;
1170 vars.temperature = T_int_pt;
1171
1173 {
1174 vars.temperature = N.dot(local_T);
1175 }
1176
1177 // porosity
1178 {
1179 vars_prev.porosity = porosity_prev;
1180
1181 porosity =
1183 ? porosity_prev
1185 .template value<double>(vars, vars_prev, pos, t,
1186 dt);
1187
1188 vars.porosity = porosity;
1189 }
1190
1191 auto const& retardation_factor =
1193 .template value<double>(vars, pos, t, dt);
1194
1195 auto const& solute_dispersivity_transverse = medium.template value<
1196 double>(
1198 auto const& solute_dispersivity_longitudinal =
1199 medium.template value<double>(
1201 longitudinal_dispersivity);
1202
1203 // Use the fluid density model to compute the density
1204 auto const density =
1206 .template value<double>(vars, pos, t, dt);
1207 auto const decay_rate =
1209 .template value<double>(vars, pos, t, dt);
1210
1211 auto const& pore_diffusion_coefficient =
1214 .value(vars, pos, t, dt));
1215
1218 vars, pos, t, dt));
1219 // Use the viscosity model to compute the viscosity
1221 .template value<double>(vars, pos, t, dt);
1222
1223 GlobalDimMatrixType const K_over_mu = K / mu;
1224 GlobalDimVectorType const velocity =
1226 ? GlobalDimVectorType(-K_over_mu *
1227 (dNdx * local_p - density * b))
1228 : GlobalDimVectorType(-K_over_mu * dNdx * local_p);
1229
1230 GlobalDimMatrixType const hydrodynamic_dispersion =
1233 pore_diffusion_coefficient, velocity, porosity,
1234 solute_dispersivity_transverse,
1235 solute_dispersivity_longitudinal);
1236
1237 double const R_times_phi = retardation_factor * porosity;
1238 auto const N_t_N = (N.transpose() * N).eval();
1239
1241 {
1242 const double drho_dC =
1244 .template dValue<double>(
1246 pos, t, dt);
1247 local_M.noalias() +=
1248 N_t_N * (R_times_phi * C_int_pt * drho_dC * w);
1249 }
1250
1251 local_M.noalias() += N_t_N * (R_times_phi * density * w);
1252
1253 // coupling term
1255 {
1256 double const p_dot = (p_int_pt - N.dot(local_p_prev)) / dt;
1257
1258 const double drho_dp =
1260 .template dValue<double>(vars,
1262 liquid_phase_pressure,
1263 pos, t, dt);
1264
1265 local_K.noalias() +=
1266 N_t_N * ((R_times_phi * drho_dp * p_dot) * w) -
1267 dNdx.transpose() * velocity * N * (density * w);
1268 }
1269 else
1270 {
1271 ip_flux_vector.emplace_back(velocity * density);
1272 average_velocity_norm += velocity.norm();
1273 }
1274 local_K.noalias() +=
1275 N_t_N * (decay_rate * R_times_phi * density * w);
1276
1277 KCC_Laplacian.noalias() += dNdx.transpose() *
1278 hydrodynamic_dispersion * dNdx *
1279 (density * w);
1280 }
1281
1283 {
1285 typename ShapeFunction::MeshElement>(
1287 _process_data.shape_matrix_cache, ip_flux_vector,
1288 average_velocity_norm /
1289 static_cast<double>(n_integration_points),
1290 KCC_Laplacian);
1291 }
1292 local_K.noalias() += KCC_Laplacian;
1293 }
1294
1296 double const t, double const dt, Eigen::VectorXd const& local_x,
1297 Eigen::VectorXd const& local_x_prev, int const process_id,
1298 std::vector<double>& local_b_data,
1299 std::vector<double>& local_Jac_data) override
1300 {
1301 if (process_id == _process_data.hydraulic_process_id)
1302 {
1303 assembleWithJacobianHydraulicEquation(t, dt, local_x, local_x_prev,
1304 local_b_data, local_Jac_data);
1305 }
1306 else
1307 {
1308 int const component_id = process_id - 1;
1310 t, dt, local_x, local_x_prev, local_b_data, local_Jac_data,
1311 component_id);
1312 }
1313 }
1314
1316 double const t, double const dt, Eigen::VectorXd const& local_x,
1317 Eigen::VectorXd const& local_x_prev, std::vector<double>& local_b_data,
1318 std::vector<double>& local_Jac_data)
1319 {
1320 auto const p = local_x.template segment<pressure_size>(pressure_index);
1321 auto const c = local_x.template segment<concentration_size>(
1323
1324 auto const p_prev = local_x_prev.segment<pressure_size>(pressure_index);
1325 auto const c_prev =
1326 local_x_prev.segment<concentration_size>(first_concentration_index);
1327
1329 local_Jac_data, pressure_size, pressure_size);
1331 local_b_data, pressure_size);
1332
1333 unsigned const n_integration_points =
1335
1338 auto const& b =
1341
1342 auto const& medium =
1344 auto const& phase = medium.phase("AqueousLiquid");
1345
1348
1349 auto const& Ns =
1351 .NsHigherOrder<typename ShapeFunction::MeshElement>();
1352
1353 for (unsigned ip(0); ip < n_integration_points; ++ip)
1354 {
1355 auto& ip_data = _ip_data[ip];
1356 auto const& dNdx = ip_data.dNdx;
1357 auto const& w = ip_data.integration_weight;
1358 auto const& N = Ns[ip];
1359 auto& phi = ip_data.porosity;
1360 auto const& phi_prev = ip_data.porosity_prev;
1361
1362 double const p_ip = N.dot(p);
1363 double const c_ip = N.dot(c);
1364
1365 double const cdot_ip = (c_ip - N.dot(c_prev)) / dt;
1366
1367 vars.liquid_phase_pressure = p_ip;
1368 vars.concentration = c_ip;
1369
1370 // porosity
1371 {
1372 vars_prev.porosity = phi_prev;
1373
1375 ? phi_prev
1377 .template value<double>(vars, vars_prev, pos, t,
1378 dt);
1379
1380 vars.porosity = phi;
1381 }
1382
1383 auto const rho = phase[MaterialPropertyLib::PropertyType::density]
1384 .template value<double>(vars, pos, t, dt);
1385
1388 vars, pos, t, dt));
1389
1391 .template value<double>(vars, pos, t, dt);
1392
1393 auto const drho_dp =
1395 .template dValue<double>(
1396 vars,
1398 pos, t, dt);
1399 auto const drho_dc =
1401 .template dValue<double>(
1403 t, dt);
1404
1405 // matrix assembly
1406 local_Jac.noalias() += w * N.transpose() * phi * drho_dp / dt * N +
1407 w * dNdx.transpose() * rho * k / mu * dNdx;
1408
1409 local_rhs.noalias() -=
1410 w * N.transpose() * phi *
1411 (drho_dp * N * p_prev + drho_dc * cdot_ip) +
1412 w * rho * dNdx.transpose() * k / mu * dNdx * p;
1413
1415 {
1416 local_rhs.noalias() +=
1417 w * rho * dNdx.transpose() * k / mu * rho * b;
1418 }
1419 }
1420 }
1421
1423 double const t, double const dt, Eigen::VectorXd const& local_x,
1424 Eigen::VectorXd const& local_x_prev, std::vector<double>& local_b_data,
1425 std::vector<double>& local_Jac_data, int const component_id)
1426 {
1427 auto const concentration_index =
1429
1430 auto const p = local_x.template segment<pressure_size>(pressure_index);
1431 auto const c =
1432 local_x.template segment<concentration_size>(concentration_index);
1433 auto const c_prev =
1434 local_x_prev.segment<concentration_size>(concentration_index);
1435
1438 {
1440 }
1441
1443 local_Jac_data, concentration_size, concentration_size);
1445 local_b_data, concentration_size);
1446
1447 LocalBlockMatrixType KCC_Laplacian =
1448 LocalBlockMatrixType::Zero(concentration_size, concentration_size);
1449
1450 unsigned const n_integration_points =
1452
1453 std::vector<GlobalDimVectorType> ip_flux_vector;
1454 double average_velocity_norm = 0.0;
1455 ip_flux_vector.reserve(n_integration_points);
1456
1459
1460 auto const& b =
1463
1466
1467 auto const& medium =
1469 auto const& phase = medium.phase("AqueousLiquid");
1470 auto const& component = phase.component(
1471 _transport_process_variables[component_id].get().getName());
1472
1473 auto const& Ns =
1475 .NsHigherOrder<typename ShapeFunction::MeshElement>();
1476
1477 for (unsigned ip(0); ip < n_integration_points; ++ip)
1478 {
1479 auto& ip_data = _ip_data[ip];
1480 auto const& dNdx = ip_data.dNdx;
1481 auto const& w = ip_data.integration_weight;
1482 auto const& N = Ns[ip];
1483 auto& phi = ip_data.porosity;
1484 auto const& phi_prev = ip_data.porosity_prev;
1485
1486 double const p_ip = N.dot(p);
1487 double const c_ip = N.dot(c);
1488
1489 vars.liquid_phase_pressure = p_ip;
1490 vars.concentration = c_ip;
1491
1493 {
1494 vars.temperature = N.dot(T);
1495 }
1496
1497 // porosity
1498 {
1499 vars_prev.porosity = phi_prev;
1500
1502 ? phi_prev
1504 .template value<double>(vars, vars_prev, pos, t,
1505 dt);
1506
1507 vars.porosity = phi;
1508 }
1509
1510 auto const R =
1512 .template value<double>(vars, pos, t, dt);
1513
1514 auto const alpha_T = medium.template value<double>(
1516 auto const alpha_L = medium.template value<double>(
1518
1519 auto const rho = phase[MaterialPropertyLib::PropertyType::density]
1520 .template value<double>(vars, pos, t, dt);
1521 // first-order decay constant
1522 auto const alpha =
1524 .template value<double>(vars, pos, t, dt);
1525
1528 .value(vars, pos, t, dt));
1529
1532 vars, pos, t, dt));
1534 .template value<double>(vars, pos, t, dt);
1535 // Darcy flux
1536 GlobalDimVectorType const q =
1538 ? GlobalDimVectorType(-k / mu * (dNdx * p - rho * b))
1539 : GlobalDimVectorType(-k / mu * dNdx * p);
1540
1542 _process_data.stabilizer, _element.getID(), Dp, q, phi, alpha_T,
1543 alpha_L);
1544
1545 // matrix assembly
1546 local_Jac.noalias() +=
1547 w * rho * N.transpose() * phi * R * (alpha + 1 / dt) * N;
1548
1549 KCC_Laplacian.noalias() += w * rho * dNdx.transpose() * D * dNdx;
1550
1551 auto const cdot = (c - c_prev) / dt;
1552 local_rhs.noalias() -=
1553 w * rho * N.transpose() * phi * R * N * (cdot + alpha * c);
1554
1555 ip_flux_vector.emplace_back(q * rho);
1556 average_velocity_norm += q.norm();
1557 }
1558
1561 _process_data.shape_matrix_cache, ip_flux_vector,
1562 average_velocity_norm / static_cast<double>(n_integration_points),
1563 KCC_Laplacian);
1564
1565 local_rhs.noalias() -= KCC_Laplacian * c;
1566
1567 local_Jac.noalias() += KCC_Laplacian;
1568 }
1569
1571 double const t, double const dt, Eigen::VectorXd const& local_x,
1572 std::vector<double>& local_M_data, std::vector<double>& local_K_data,
1573 std::vector<double>& local_b_data,
1574 int const transport_process_id) override
1575 {
1576 auto const local_C = local_x.template segment<concentration_size>(
1578 (transport_process_id - 1) * concentration_size);
1579
1581 local_M_data, concentration_size, concentration_size);
1583 local_K_data, concentration_size, concentration_size);
1585 local_b_data, concentration_size);
1586
1587 unsigned const n_integration_points =
1589
1592
1595
1596 auto const& medium =
1598 auto const component_id = transport_process_id - 1;
1599
1600 auto const& Ns =
1602 .NsHigherOrder<typename ShapeFunction::MeshElement>();
1603
1604 for (unsigned ip(0); ip < n_integration_points; ++ip)
1605 {
1606 auto& ip_data = _ip_data[ip];
1607 auto const w = ip_data.integration_weight;
1608 auto const& N = Ns[ip];
1609 auto& porosity = ip_data.porosity;
1610 auto const& porosity_prev = ip_data.porosity_prev;
1611 auto const chemical_system_id = ip_data.chemical_system_id;
1612
1613 double C_int_pt = 0.0;
1614 NumLib::shapeFunctionInterpolate(local_C, N, C_int_pt);
1615
1616 vars.concentration = C_int_pt;
1617
1618 auto const porosity_dot = (porosity - porosity_prev) / dt;
1619
1620 // porosity
1621 {
1622 vars_prev.porosity = porosity_prev;
1623
1624 porosity =
1626 ? porosity_prev
1628 .template value<double>(vars, vars_prev, pos, t,
1629 dt);
1630 }
1631
1632 local_M.noalias() += w * N.transpose() * porosity * N;
1633
1634 local_K.noalias() += w * N.transpose() * porosity_dot * N;
1635
1636 if (chemical_system_id == -1)
1637 {
1638 continue;
1639 }
1640
1641 auto const C_post_int_pt =
1643 component_id, chemical_system_id);
1644
1645 local_b.noalias() +=
1646 w * N.transpose() * porosity * (C_post_int_pt - C_int_pt) / dt;
1647 }
1648 }
1649
1650 std::vector<double> const& getIntPtDarcyVelocity(
1651 const double t,
1652 std::vector<GlobalVector*> const& x,
1653 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_table,
1654 std::vector<double>& cache) const override
1655 {
1656 assert(x.size() == dof_table.size());
1657
1658 auto const n_processes = x.size();
1659 std::vector<std::vector<double>> local_x;
1660 local_x.reserve(n_processes);
1661
1662 for (std::size_t process_id = 0; process_id < n_processes; ++process_id)
1663 {
1664 auto const indices =
1665 NumLib::getIndices(_element.getID(), *dof_table[process_id]);
1666 assert(!indices.empty());
1667 local_x.push_back(x[process_id]->get(indices));
1668 }
1669
1670 // only one process, must be monolithic.
1671 if (n_processes == 1)
1672 {
1673 auto const local_p = Eigen::Map<const NodalVectorType>(
1674 &local_x[0][pressure_index], pressure_size);
1675 auto const local_C = Eigen::Map<const NodalVectorType>(
1677 NodalVectorType local_T;
1678 local_T.setConstant(ShapeFunction::NPOINTS,
1679 std::numeric_limits<double>::quiet_NaN());
1680 int const temperature_index =
1681 _process_data.isothermal ? -1 : ShapeFunction::NPOINTS;
1682 if (temperature_index != -1)
1683 {
1684 local_T = Eigen::Map<const NodalVectorType>(
1685 &local_x[0][temperature_index], temperature_size);
1686 }
1687 return calculateIntPtDarcyVelocity(t, local_p, local_C, local_T,
1688 cache);
1689 }
1690
1691 // multiple processes, must be staggered.
1692 {
1693 constexpr int pressure_process_id = 0;
1694 constexpr int concentration_process_id = 1;
1695 constexpr int temperature_process_id = -1; // The temperature
1696 // coupling in staggered
1697 // scheme not available.
1698 auto const local_p = Eigen::Map<const NodalVectorType>(
1699 &local_x[pressure_process_id][0], pressure_size);
1700 auto const local_C = Eigen::Map<const NodalVectorType>(
1701 &local_x[concentration_process_id][0], concentration_size);
1702 NodalVectorType local_T;
1703 local_T.setConstant(ShapeFunction::NPOINTS,
1704 std::numeric_limits<double>::quiet_NaN());
1705 if (temperature_process_id != -1)
1706 {
1707 local_T = Eigen::Map<const NodalVectorType>(
1708 &local_x[temperature_process_id][0], temperature_size);
1709 }
1710 return calculateIntPtDarcyVelocity(t, local_p, local_C, local_T,
1711 cache);
1712 }
1713 }
1714
1715 std::vector<double> const& calculateIntPtDarcyVelocity(
1716 const double t,
1717 Eigen::Ref<const NodalVectorType> const& p_nodal_values,
1718 Eigen::Ref<const NodalVectorType> const& C_nodal_values,
1719 Eigen::Ref<const NodalVectorType> const& T_nodal_values,
1720 std::vector<double>& cache) const
1721 {
1722 auto const n_integration_points =
1724
1725 cache.clear();
1726 auto cache_mat = MathLib::createZeroedMatrix<
1727 Eigen::Matrix<double, GlobalDim, Eigen::Dynamic, Eigen::RowMajor>>(
1728 cache, GlobalDim, n_integration_points);
1729
1732
1733 auto const& b =
1736
1738
1739 auto const& medium =
1741 auto const& phase = medium.phase("AqueousLiquid");
1742
1743 auto const& Ns =
1745 .NsHigherOrder<typename ShapeFunction::MeshElement>();
1746
1747 for (unsigned ip = 0; ip < n_integration_points; ++ip)
1748 {
1749 auto const& ip_data = _ip_data[ip];
1750 auto const& dNdx = ip_data.dNdx;
1751 auto const& N = Ns[ip];
1752 auto const& porosity = ip_data.porosity;
1753
1754 double C_int_pt = 0.0;
1755 double p_int_pt = 0.0;
1756 double T_int_pt = 0.0;
1757
1758 NumLib::shapeFunctionInterpolate(C_nodal_values, N, C_int_pt);
1759 NumLib::shapeFunctionInterpolate(p_nodal_values, N, p_int_pt);
1760 NumLib::shapeFunctionInterpolate(T_nodal_values, N, T_int_pt);
1761
1762 vars.concentration = C_int_pt;
1763 vars.liquid_phase_pressure = p_int_pt;
1764 vars.porosity = porosity;
1765 vars.temperature = T_int_pt;
1766
1767 // TODO (naumov) Temporary value not used by current material
1768 // models. Need extension of secondary variables interface.
1769 double const dt = std::numeric_limits<double>::quiet_NaN();
1772 vars, pos, t, dt));
1774 .template value<double>(vars, pos, t, dt);
1775 GlobalDimMatrixType const K_over_mu = K / mu;
1776
1777 cache_mat.col(ip).noalias() = -K_over_mu * dNdx * p_nodal_values;
1779 {
1780 auto const rho_w =
1782 .template value<double>(vars, pos, t, dt);
1783 // here it is assumed that the vector b is directed 'downwards'
1784 cache_mat.col(ip).noalias() += K_over_mu * rho_w * b;
1785 }
1786 }
1787
1788 return cache;
1789 }
1790
1791 Eigen::Map<const Eigen::RowVectorXd> getShapeMatrix(
1792 const unsigned integration_point) const override
1793 {
1795 typename ShapeFunction::MeshElement>()[integration_point];
1796
1797 // assumes N is stored contiguously in memory
1798 return Eigen::Map<const Eigen::RowVectorXd>(N.data(), N.size());
1799 }
1800
1801 Eigen::Vector3d getFlux(MathLib::Point3d const& pnt_local_coords,
1802 double const t,
1803 std::vector<double> const& local_x) const override
1804 {
1805 auto const local_p = Eigen::Map<const NodalVectorType>(
1806 &local_x[pressure_index], pressure_size);
1807 auto const local_C = Eigen::Map<const NodalVectorType>(
1809
1810 // Eval shape matrices at given point
1811 // Note: Axial symmetry is set to false here, because we only need dNdx
1812 // here, which is not affected by axial symmetry.
1813 auto const shape_matrices =
1815 GlobalDim>(
1816 _element, false /*is_axially_symmetric*/,
1817 std::array{pnt_local_coords})[0];
1818
1821 auto const& b =
1824
1826
1827 auto const& medium =
1829 auto const& phase = medium.phase("AqueousLiquid");
1830
1831 // local_x contains the local concentration and pressure values
1832 double c_int_pt;
1833 NumLib::shapeFunctionInterpolate(local_C, shape_matrices.N, c_int_pt);
1834 vars.concentration = c_int_pt;
1835
1836 double p_int_pt;
1837 NumLib::shapeFunctionInterpolate(local_p, shape_matrices.N, p_int_pt);
1838 vars.liquid_phase_pressure = p_int_pt;
1839
1840 // TODO (naumov) Temporary value not used by current material models.
1841 // Need extension of secondary variables interface.
1842 double const dt = std::numeric_limits<double>::quiet_NaN();
1845 vars, pos, t, dt));
1846
1848 .template value<double>(vars, pos, t, dt);
1849 GlobalDimMatrixType const K_over_mu = K / mu;
1850
1851 GlobalDimVectorType q = -K_over_mu * shape_matrices.dNdx * local_p;
1852 auto const rho_w = phase[MaterialPropertyLib::PropertyType::density]
1853 .template value<double>(vars, pos, t, dt);
1855 {
1856 q += K_over_mu * rho_w * b;
1857 }
1858 Eigen::Vector3d flux(0.0, 0.0, 0.0);
1859 flux.head<GlobalDim>() = rho_w * q;
1860 return flux;
1861 }
1862
1864 double const t,
1865 double const /*dt*/,
1866 Eigen::VectorXd const& local_x,
1867 Eigen::VectorXd const& /*local_x_prev*/) override
1868 {
1869 auto const local_p =
1870 local_x.template segment<pressure_size>(pressure_index);
1871 auto const local_C = local_x.template segment<concentration_size>(
1873 auto const local_T = getLocalTemperature(t, local_x);
1874
1875 std::vector<double> ele_velocity;
1876 calculateIntPtDarcyVelocity(t, local_p, local_C, local_T, ele_velocity);
1877
1878 auto const n_integration_points =
1880 auto const ele_velocity_mat =
1881 MathLib::toMatrix(ele_velocity, GlobalDim, n_integration_points);
1882
1883 auto const ele_id = _element.getID();
1884 Eigen::Map<LocalVectorType>(
1885 &(*_process_data.mesh_prop_velocity)[ele_id * GlobalDim],
1886 GlobalDim) =
1887 ele_velocity_mat.rowwise().sum() / n_integration_points;
1888 }
1889
1891 std::size_t const ele_id) override
1892 {
1893 auto const n_integration_points =
1895
1897 {
1898 auto const& medium = *_process_data.media_map.getMedium(ele_id);
1899
1900 for (auto& ip_data : _ip_data)
1901 {
1902 ip_data.porosity = ip_data.porosity_prev;
1903
1905 ->updatePorosityPostReaction(ip_data.chemical_system_id,
1906 medium, ip_data.porosity);
1907 }
1908
1910 std::accumulate(_ip_data.begin(), _ip_data.end(), 0.,
1911 [](double const s, auto const& ip)
1912 { return s + ip.porosity; }) /
1913 n_integration_points;
1914 }
1915
1916 std::vector<GlobalIndexType> chemical_system_indices;
1917 chemical_system_indices.reserve(n_integration_points);
1918 std::transform(_ip_data.begin(), _ip_data.end(),
1919 std::back_inserter(chemical_system_indices),
1920 [](auto const& ip_data)
1921 { return ip_data.chemical_system_id; });
1922
1924 ele_id, chemical_system_indices);
1925 }
1926
1927 std::vector<double> const& getIntPtMolarFlux(
1928 const double t, std::vector<GlobalVector*> const& x,
1929 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_tables,
1930 std::vector<double>& cache, int const component_id) const override
1931 {
1932 std::vector<double> local_x_vec;
1933
1934 auto const n_processes = x.size();
1935 for (std::size_t process_id = 0; process_id < n_processes; ++process_id)
1936 {
1937 auto const indices =
1938 NumLib::getIndices(_element.getID(), *dof_tables[process_id]);
1939 assert(!indices.empty());
1940 auto const local_solution = x[process_id]->get(indices);
1941 local_x_vec.insert(std::end(local_x_vec),
1942 std::begin(local_solution),
1943 std::end(local_solution));
1944 }
1945 auto const local_x = MathLib::toVector(local_x_vec);
1946
1947 auto const p = local_x.template segment<pressure_size>(pressure_index);
1948 auto const c = local_x.template segment<concentration_size>(
1950
1951 auto const n_integration_points =
1953
1954 cache.clear();
1955 auto cache_mat = MathLib::createZeroedMatrix<
1956 Eigen::Matrix<double, GlobalDim, Eigen::Dynamic, Eigen::RowMajor>>(
1957 cache, GlobalDim, n_integration_points);
1958
1961
1962 auto const& b =
1965
1967
1968 auto const& medium =
1970 auto const& phase = medium.phase("AqueousLiquid");
1971
1972 auto const& component = phase.component(
1973 _transport_process_variables[component_id].get().getName());
1974
1975 auto const& Ns =
1977 .NsHigherOrder<typename ShapeFunction::MeshElement>();
1978
1979 for (unsigned ip = 0; ip < n_integration_points; ++ip)
1980 {
1981 auto const& ip_data = _ip_data[ip];
1982 auto const& dNdx = ip_data.dNdx;
1983 auto const& N = Ns[ip];
1984 auto const& phi = ip_data.porosity;
1985
1986 double const p_ip = N.dot(p);
1987 double const c_ip = N.dot(c);
1988
1989 vars.concentration = c_ip;
1990 vars.liquid_phase_pressure = p_ip;
1991 vars.porosity = phi;
1992
1993 double const dt = std::numeric_limits<double>::quiet_NaN();
1994
1997 vars, pos, t, dt));
1999 .template value<double>(vars, pos, t, dt);
2000 auto const rho = phase[MaterialPropertyLib::PropertyType::density]
2001 .template value<double>(vars, pos, t, dt);
2002
2003 // Darcy flux
2004 GlobalDimVectorType const q =
2006 ? GlobalDimVectorType(-k / mu * (dNdx * p - rho * b))
2007 : GlobalDimVectorType(-k / mu * dNdx * p);
2008
2009 auto const alpha_T = medium.template value<double>(
2011 auto const alpha_L = medium.template value<double>(
2015 .value(vars, pos, t, dt));
2016
2017 // Hydrodynamic dispersion
2019 _process_data.stabilizer, _element.getID(), Dp, q, phi, alpha_T,
2020 alpha_L);
2021
2022 cache_mat.col(ip).noalias() = q * c_ip - D * dNdx * c;
2023 }
2024
2025 return cache;
2026 }
2027
2028 void postTimestepConcrete(Eigen::VectorXd const& /*local_x*/,
2029 Eigen::VectorXd const& /*local_x_prev*/,
2030 double const /*t*/, double const /*dt*/,
2031 int const /*process_id*/) override
2032 {
2033 unsigned const n_integration_points =
2035
2036 for (unsigned ip = 0; ip < n_integration_points; ip++)
2037 {
2038 _ip_data[ip].pushBackState();
2039 }
2040 }
2041
2042private:
2045
2047 std::vector<std::reference_wrapper<ProcessVariable>> const
2049
2050 std::vector<IntegrationPointData<GlobalDimNodalMatrixType>> _ip_data;
2051
2053 MaterialPropertyLib::VariableArray const& vars, const double porosity,
2054 const double fluid_density, const double specific_heat_capacity_fluid,
2055 ParameterLib::SpatialPosition const& pos, double const t,
2056 double const dt)
2057 {
2058 auto const& medium =
2059 *_process_data.media_map.getMedium(this->_element.getID());
2060 auto const& solid_phase = medium.phase("Solid");
2061
2062 auto const specific_heat_capacity_solid =
2063 solid_phase
2064 .property(
2066 .template value<double>(vars, pos, t, dt);
2067
2068 auto const solid_density =
2069 solid_phase.property(MaterialPropertyLib::PropertyType::density)
2070 .template value<double>(vars, pos, t, dt);
2071
2072 return solid_density * specific_heat_capacity_solid * (1 - porosity) +
2073 fluid_density * specific_heat_capacity_fluid * porosity;
2074 }
2075
2078 const double fluid_density, const double specific_heat_capacity_fluid,
2079 const GlobalDimVectorType& velocity,
2080 ParameterLib::SpatialPosition const& pos, double const t,
2081 double const dt)
2082 {
2083 auto const& medium =
2085
2086 auto thermal_conductivity =
2088 medium
2089 .property(
2091 .value(vars, pos, t, dt));
2092
2093 auto const thermal_dispersivity_transversal =
2094 medium
2096 thermal_transversal_dispersivity)
2097 .template value<double>();
2098
2099 auto const thermal_dispersivity_longitudinal =
2100 medium
2102 thermal_longitudinal_dispersivity)
2103 .template value<double>();
2104
2105 // Thermal conductivity is moved outside and zero matrix is passed
2106 // instead due to multiplication with fluid's density times specific
2107 // heat capacity.
2108 return thermal_conductivity +
2109 fluid_density * specific_heat_capacity_fluid *
2112 GlobalDimMatrixType::Zero(GlobalDim, GlobalDim),
2113 velocity, 0 /* phi */, thermal_dispersivity_transversal,
2114 thermal_dispersivity_longitudinal);
2115 }
2116
2118 Eigen::VectorXd const& local_x) const
2119 {
2120 NodalVectorType local_T;
2122 {
2124 {
2126 _element, t);
2127 }
2128 else
2129 {
2130 local_T = NodalVectorType::Zero(temperature_size);
2131 }
2132 }
2133 else
2134 {
2135 local_T =
2136 local_x.template segment<temperature_size>(temperature_index);
2137 }
2138 return local_T;
2139 }
2140};
2141
2142} // namespace ComponentTransport
2143} // namespace ProcessLib
GlobalMatrix::IndexType GlobalIndexType
std::string getName(std::string const &line)
Returns the name/title from the "Zone"-description.
virtual void updatePorosityPostReaction(GlobalIndexType const &, MaterialPropertyLib::Medium const &, double &)
virtual double getKineticPrefactor(std::size_t reaction_id) const
virtual void computeSecondaryVariable(std::size_t const, std::vector< GlobalIndexType > const &)
virtual void setChemicalSystemConcrete(std::vector< double > const &, GlobalIndexType const &, MaterialPropertyLib::Medium const *, MaterialPropertyLib::VariableArray const &, ParameterLib::SpatialPosition const &, double const, double const)
virtual void updateVolumeFractionPostReaction(GlobalIndexType const &, MaterialPropertyLib::Medium const &, ParameterLib::SpatialPosition const &, double const, double const, double const)
std::vector< GlobalIndexType > chemical_system_index_map
virtual Eigen::SparseMatrix< double > const * getStoichiometricMatrix() const
virtual double getConcentration(int const, GlobalIndexType const) const
virtual void initializeChemicalSystemConcrete(std::vector< double > const &, GlobalIndexType const &, MaterialPropertyLib::Medium const &, ParameterLib::SpatialPosition const &, double const)
Phase const & phase(std::size_t index) const
Definition Medium.cpp:33
Property const & property(PropertyType const &p) const
Definition Phase.cpp:53
Component const & component(std::size_t const &index) const
Definition Phase.cpp:33
int add(IndexType row, IndexType col, double val)
Definition EigenMatrix.h:87
Global vector based on Eigen vector.
Definition EigenVector.h:26
void add(IndexType rowId, double v)
add entry
Definition EigenVector.h:77
constexpr double getWeight() const
std::size_t getID() const
Returns the ID of the element.
Definition Element.h:91
MathLib::WeightedPoint const & getWeightedPoint(unsigned const igp) const
MathLib::RowColumnIndices< GlobalIndexType > RowColumnIndices
auto const & NsHigherOrder() const
void setCoordinates(MathLib::Point3d const &coordinates)
void setElementID(std::size_t element_id)
virtual std::vector< double > const & getIntPtDarcyVelocity(const double t, std::vector< GlobalVector * > const &x, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_table, std::vector< double > &cache) const =0
virtual void setChemicalSystemConcrete(Eigen::VectorXd const &, double const, double const)=0
virtual void postSpeciationCalculation(std::size_t const ele_id, double const t, double const dt)=0
virtual void computeReactionRelatedSecondaryVariable(std::size_t const ele_id)=0
void initializeChemicalSystem(std::size_t const mesh_item_id, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_tables, std::vector< GlobalVector * > const &x, double const t)
void setChemicalSystem(std::size_t const mesh_item_id, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_tables, std::vector< GlobalVector * > const &x, double const t, double const dt)
virtual void assembleReactionEquationConcrete(double const t, double const dt, Eigen::VectorXd const &local_x, std::vector< double > &local_M_data, std::vector< double > &local_K_data, std::vector< double > &local_b_data, int const transport_process_id)=0
void assembleReactionEquation(std::size_t const mesh_item_id, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_tables, std::vector< GlobalVector * > const &x, double const t, double const dt, GlobalMatrix &M, GlobalMatrix &K, GlobalVector &b, int const process_id)
virtual void initializeChemicalSystemConcrete(Eigen::VectorXd const &, double const)=0
virtual std::vector< double > const & getIntPtMolarFlux(const double t, std::vector< GlobalVector * > const &x, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_table, std::vector< double > &cache, int const component_id) const =0
NodalVectorType getLocalTemperature(double const t, Eigen::VectorXd const &local_x) const
typename ShapeMatricesType::GlobalDimVectorType GlobalDimVectorType
void assembleForStaggeredScheme(double const t, double const dt, Eigen::VectorXd const &local_x, Eigen::VectorXd const &local_x_prev, int const process_id, std::vector< double > &local_M_data, std::vector< double > &local_K_data, std::vector< double > &local_b_data) override
typename ShapeMatricesType::ShapeMatrices ShapeMatrices
void assembleWithJacobianHydraulicEquation(double const t, double const dt, Eigen::VectorXd const &local_x, Eigen::VectorXd const &local_x_prev, std::vector< double > &local_b_data, std::vector< double > &local_Jac_data)
void assembleHeatTransportEquation(double const t, double const dt, Eigen::VectorXd const &local_x, Eigen::VectorXd const &, std::vector< double > &local_M_data, std::vector< double > &local_K_data, std::vector< double > &)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > LocalMatrixType
void postTimestepConcrete(Eigen::VectorXd const &, Eigen::VectorXd const &, double const, double const, int const) override
std::vector< double > const & getIntPtMolarFlux(const double t, std::vector< GlobalVector * > const &x, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_tables, std::vector< double > &cache, int const component_id) const override
void postSpeciationCalculation(std::size_t const ele_id, double const t, double const dt) override
NumLib::GenericIntegrationMethod const & _integration_method
std::vector< double > const & calculateIntPtDarcyVelocity(const double t, Eigen::Ref< const NodalVectorType > const &p_nodal_values, Eigen::Ref< const NodalVectorType > const &C_nodal_values, Eigen::Ref< const NodalVectorType > const &T_nodal_values, std::vector< double > &cache) const
void initializeChemicalSystemConcrete(Eigen::VectorXd const &local_x, double const t) override
void computeReactionRelatedSecondaryVariable(std::size_t const ele_id) override
void assembleBlockMatrices(GlobalDimVectorType const &b, int const component_id, double const t, double const dt, Eigen::Ref< const NodalVectorType > const &C_nodal_values, Eigen::Ref< const NodalVectorType > const &p_nodal_values, Eigen::Ref< LocalBlockMatrixType > KCC, Eigen::Ref< LocalBlockMatrixType > MCC, Eigen::Ref< LocalBlockMatrixType > MCp, Eigen::Ref< LocalBlockMatrixType > MpC, Eigen::Ref< LocalBlockMatrixType > Kpp, Eigen::Ref< LocalBlockMatrixType > Mpp, Eigen::Ref< LocalSegmentVectorType > Bp)
typename ShapeMatricesType::template MatrixType< pressure_size, pressure_size > LocalBlockMatrixType
typename ShapeMatricesType::GlobalDimMatrixType GlobalDimMatrixType
void assembleWithJacobianForStaggeredScheme(double const t, double const dt, Eigen::VectorXd const &local_x, Eigen::VectorXd const &local_x_prev, int const process_id, std::vector< double > &local_b_data, std::vector< double > &local_Jac_data) override
std::vector< IntegrationPointData< GlobalDimNodalMatrixType > > _ip_data
ComponentTransportProcessData const & _process_data
Eigen::Map< const Eigen::RowVectorXd > getShapeMatrix(const unsigned integration_point) const override
Provides the shape matrix at the given integration point.
ShapeMatrixPolicyType< ShapeFunction, GlobalDim > ShapeMatricesType
void computeSecondaryVariableConcrete(double const t, double const, Eigen::VectorXd const &local_x, Eigen::VectorXd const &) override
std::vector< std::reference_wrapper< ProcessVariable > > const _transport_process_variables
void assembleHydraulicEquation(double const t, double const dt, Eigen::VectorXd const &local_x, Eigen::VectorXd const &local_x_prev, std::vector< double > &local_M_data, std::vector< double > &local_K_data, std::vector< double > &local_b_data)
typename ShapeMatricesType::GlobalDimNodalMatrixType GlobalDimNodalMatrixType
typename ShapeMatricesType::NodalRowVectorType NodalRowVectorType
std::vector< double > const & getIntPtDarcyVelocity(const double t, std::vector< GlobalVector * > const &x, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_table, std::vector< double > &cache) const override
void assembleComponentTransportEquation(double const t, double const dt, Eigen::VectorXd const &local_x, Eigen::VectorXd const &local_x_prev, std::vector< double > &local_M_data, std::vector< double > &local_K_data, std::vector< double > &, int const transport_process_id)
Eigen::Vector3d getFlux(MathLib::Point3d const &pnt_local_coords, double const t, std::vector< double > const &local_x) const override
GlobalDimMatrixType getThermalConductivityDispersivity(MaterialPropertyLib::VariableArray const &vars, const double fluid_density, const double specific_heat_capacity_fluid, const GlobalDimVectorType &velocity, ParameterLib::SpatialPosition const &pos, double const t, double const dt)
void assemble(double const t, double const dt, std::vector< double > const &local_x, std::vector< double > const &, std::vector< double > &local_M_data, std::vector< double > &local_K_data, std::vector< double > &local_b_data) override
void assembleWithJacobianComponentTransportEquation(double const t, double const dt, Eigen::VectorXd const &local_x, Eigen::VectorXd const &local_x_prev, std::vector< double > &local_b_data, std::vector< double > &local_Jac_data, int const component_id)
Eigen::Matrix< double, Eigen::Dynamic, 1 > LocalVectorType
double getHeatEnergyCoefficient(MaterialPropertyLib::VariableArray const &vars, const double porosity, const double fluid_density, const double specific_heat_capacity_fluid, ParameterLib::SpatialPosition const &pos, double const t, double const dt)
void assembleReactionEquationConcrete(double const t, double const dt, Eigen::VectorXd const &local_x, std::vector< double > &local_M_data, std::vector< double > &local_K_data, std::vector< double > &local_b_data, int const transport_process_id) override
LocalAssemblerData(MeshLib::Element const &element, std::size_t const local_matrix_size, NumLib::GenericIntegrationMethod const &integration_method, bool is_axially_symmetric, ComponentTransportProcessData const &process_data, std::vector< std::reference_wrapper< ProcessVariable > > const &transport_process_variables)
typename ShapeMatricesType::template VectorType< pressure_size > LocalSegmentVectorType
void assembleKCmCn(int const component_id, double const t, double const dt, Eigen::Ref< LocalBlockMatrixType > KCmCn, double const stoichiometric_coefficient, double const kinetic_prefactor)
void setChemicalSystemConcrete(Eigen::VectorXd const &local_x, double const t, double dt) override
typename ShapeMatricesType::NodalVectorType NodalVectorType
Eigen::Matrix< double, GlobalDim, GlobalDim > formEigenTensor(MaterialPropertyLib::PropertyDataType const &values)
@ longitudinal_dispersivity
used to compute the hydrodynamic dispersion tensor.
@ transversal_dispersivity
used to compute the hydrodynamic dispersion tensor.
@ retardation_factor
specify retardation factor used in component transport process.
Eigen::Map< Vector > createZeroedVector(std::vector< double > &data, Eigen::VectorXd::Index size)
Eigen::Map< const Vector > toVector(std::vector< double > const &data, Eigen::VectorXd::Index size)
Creates an Eigen mapped vector from the given data vector.
Eigen::Map< Matrix > createZeroedMatrix(std::vector< double > &data, Eigen::MatrixXd::Index rows, Eigen::MatrixXd::Index cols)
Eigen::Map< const Matrix > toMatrix(std::vector< double > const &data, Eigen::MatrixXd::Index rows, Eigen::MatrixXd::Index cols)
void shapeFunctionInterpolate(const NodalValues &, const ShapeMatrix &)
void assembleAdvectionMatrix(IPData const &ip_data_vector, NumLib::ShapeMatrixCache const &shape_matrix_cache, std::vector< FluxVectorType > const &ip_flux_vector, Eigen::MatrixBase< Derived > &laplacian_matrix)
std::vector< GlobalIndexType > getIndices(std::size_t const mesh_item_id, NumLib::LocalToGlobalIndexMap const &dof_table)
std::vector< typename ShapeMatricesType::ShapeMatrices, Eigen::aligned_allocator< typename ShapeMatricesType::ShapeMatrices > > initShapeMatrices(MeshLib::Element const &e, bool const is_axially_symmetric, IntegrationMethod const &integration_method)
std::vector< typename ShapeMatricesType::ShapeMatrices, Eigen::aligned_allocator< typename ShapeMatricesType::ShapeMatrices > > computeShapeMatrices(MeshLib::Element const &e, bool const is_axially_symmetric, PointContainer const &points)
Eigen::MatrixXd computeHydrodynamicDispersion(NumericalStabilization const &stabilizer, std::size_t const element_id, Eigen::MatrixXd const &pore_diffusion_coefficient, Eigen::VectorXd const &velocity, double const porosity, double const solute_dispersivity_transverse, double const solute_dispersivity_longitudinal)
std::array< double, 3 > interpolateCoordinates(MeshLib::Element const &e, typename ShapeMatricesType::ShapeMatrices::ShapeType const &N)
NumLib::ShapeMatrices< NodalRowVectorType, DimNodalMatrixType, DimMatrixType, GlobalDimNodalMatrixType > ShapeMatrices
MatrixType< GlobalDim, ShapeFunction::NPOINTS > GlobalDimNodalMatrixType
MatrixType< GlobalDim, GlobalDim > GlobalDimMatrixType
VectorType< GlobalDim > GlobalDimVectorType
VectorType< ShapeFunction::NPOINTS > NodalVectorType
RowVectorType< ShapeFunction::NPOINTS > NodalRowVectorType
virtual Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > getNodalValuesOnElement(MeshLib::Element const &element, double const t) const
Returns a matrix of values for all nodes of the given element.
Definition Parameter.h:164
std::vector< Eigen::VectorXd > const projected_specific_body_force_vectors
Projected specific body force vector: R * R^T * b.
MaterialPropertyLib::MaterialSpatialDistributionMap media_map
NumLib::ShapeMatrixCache shape_matrix_cache
caches for each mesh element type the shape matrix
IntegrationPointData(GlobalDimNodalMatrixType const &dNdx_, double const &integration_weight_)