12 const mfem::Vector &pu = this->Prolongate(u);
13 const int restricted_size = operator_cache.restr_v->Height();
14 if (operator_cache.uVol.Size() != restricted_size)
16 operator_cache.uVol.SetSize(restricted_size);
17 operator_cache.uVol.UseDevice();
19 operator_cache.restr_v->Mult(pu, operator_cache.uVol);
21 const mfem::real_t advection_scale = operator_cache.stabilityAdvectionScale;
22 const mfem::real_t diffusion_scale = operator_cache.stabilityDiffusionScale;
23 const mfem::real_t surface_scale = operator_cache.stabilitySurfaceScale;
24 const bool viscous = viscousFlowModel;
26 const auto dc = device_cache;
27 const auto gas_model = *gas;
28 const mfem::real_t *state = operator_cache.uVol.Read();
29 const mfem::real_t *jacobian = operator_cache.elJac.Read();
30 const mfem::real_t *metric = operator_cache.elMetric.Read();
31 const int points = dc.num_elements * dc.ndof_scalar_el;
32 const int dofs = dc.ndof_scalar_el;
33 const int equations = dc.num_equations;
34 const int dimensions = dc.dim;
36 mfem::Vector &advective = operator_cache.stabilityAdvectiveRate;
37 mfem::Vector &diffusive = operator_cache.stabilityDiffusiveRate;
38 if (advective.Size() != points)
40 advective.SetSize(points);
41 advective.UseDevice();
42 diffusive.SetSize(points);
43 diffusive.UseDevice();
45 mfem::real_t *advective_rate = advective.Write();
46 mfem::real_t *diffusive_rate = diffusive.Write();
47 mfem::forall(points, [=] MFEM_HOST_DEVICE (
int point)
49 const int element = point / dofs;
50 const int node = point % dofs;
51 const mfem::real_t *element_state = state + element * dofs * equations;
52 mfem::real_t point_state[
MAXEQ];
55 const mfem::real_t inverse_jacobian = 1.0 / jacobian[point];
56 mfem::real_t directional_sum = 0.0;
57 mfem::real_t metric_square_sum = 0.0;
58 for (
int reference_direction = 0; reference_direction < dimensions;
59 ++reference_direction)
61 mfem::real_t velocity_dot_metric = 0.0;
62 mfem::real_t metric_norm_squared = 0.0;
63 for (
int physical_direction = 0; physical_direction < dimensions;
66 const mfem::real_t value = metric[
67 (point * dimensions + reference_direction) * dimensions
68 + physical_direction];
69 velocity_dot_metric += gas_model.velocity(S, physical_direction) * value;
70 metric_norm_squared += value * value;
73 velocity_dot_metric, metric_norm_squared,
74 gas_model.sound_speed(S), inverse_jacobian);
75 metric_square_sum += metric_norm_squared
76 * inverse_jacobian * inverse_jacobian;
78 advective_rate[point] = advection_scale * directional_sum;
81 const mfem::real_t
density = gas_model.density(S);
82 const mfem::real_t gamma = gas_model.gamma(S);
83 const mfem::real_t shear_viscosity = gas_model.viscosity(S);
84 const mfem::real_t longitudinal_viscosity =
85 mfem::real_t(4.0 / 3.0) * shear_viscosity
86 + gas_model.bulk_viscosity(S);
87 const mfem::real_t momentum_diffusivity =
89 const mfem::real_t thermal_diffusivity =
90 gas_model.thermal_conductivity(S) * gamma
92 const mfem::real_t effective_diffusivity =
94 diffusive_rate[point] = diffusion_scale * effective_diffusivity
99 diffusive_rate[point] = 0.0;
104 const mfem::real_t *advective_host = advective.HostRead();
105 const mfem::real_t *diffusive_host = diffusive.HostRead();
106 for (
int point = 0; point < points; ++point)
109 advective_host[point]);
110 estimate.diffusive_rate = std::max(estimate.diffusive_rate,
111 diffusive_host[point]);
118 const int interior_size = operator_cache.restr_f->Height();
119 const int face_points = dc.num_face_points;
120 const int interior_points = interior_size / (2 * equations);
121 if (interior_points > 0)
123 if (operator_cache.uInt.Size() != interior_size)
125 operator_cache.uInt.SetSize(interior_size);
126 operator_cache.uInt.UseDevice();
128 operator_cache.restr_f->Mult(pu, operator_cache.uInt);
129 mfem::Vector &surface = operator_cache.stabilitySurfaceRate;
130 if (surface.Size() < interior_points)
132 surface.SetSize(interior_points);
135 const mfem::real_t *face_state = operator_cache.uInt.Read();
136 const mfem::real_t *normal = dc.nor_d;
137 const mfem::real_t *weight_minus = dc.fw_minus_d;
138 const mfem::real_t *weight_plus = dc.fw_plus_d;
139 mfem::real_t *surface_rate = surface.Write();
140 mfem::forall(interior_points, [=] MFEM_HOST_DEVICE (
int point)
142 const int face = point / face_points;
143 const int face_point = point % face_points;
144 const int face_size = 2 * face_points * equations;
145 const mfem::real_t *states = face_state + face * face_size;
146 mfem::real_t minus_state[
MAXEQ];
147 mfem::real_t plus_state[
MAXEQ];
148 for (
int equation = 0; equation < equations; ++equation)
150 minus_state[equation] = states[(0 * equations + equation)
151 * face_points + face_point];
152 plus_state[equation] = states[(1 * equations + equation)
153 * face_points + face_point];
157 mfem::real_t normal_squared = 0.0;
158 mfem::real_t minus_normal_velocity = 0.0;
159 mfem::real_t plus_normal_velocity = 0.0;
160 for (
int direction = 0; direction < dimensions; ++direction)
162 const mfem::real_t normal_component =
163 normal[point * dimensions + direction];
164 normal_squared += normal_component * normal_component;
165 minus_normal_velocity += gas_model.
velocity(minus, direction)
167 plus_normal_velocity += gas_model.velocity(plus, direction)
170 const mfem::real_t normal_magnitude =
Kernels::rsqrt(normal_squared);
173 + gas_model.sound_speed(minus) * normal_magnitude,
175 + gas_model.sound_speed(plus) * normal_magnitude);
176 surface_rate[point] = normal_wave_speed
181 const mfem::real_t *surface_host = surface.HostRead();
182 for (
int point = 0; point < interior_points; ++point)
183 estimate.surface_rate = std::max(estimate.surface_rate,
184 surface_host[point]);
187 const int boundary_size = operator_cache.restr_b->Height();
188 const int boundary_points = boundary_size / equations;
189 if (boundary_points > 0)
191 if (operator_cache.uBnd.Size() != boundary_size)
193 operator_cache.uBnd.SetSize(boundary_size);
194 operator_cache.uBnd.UseDevice();
196 operator_cache.restr_b->Mult(pu, operator_cache.uBnd);
197 mfem::Vector &surface = operator_cache.stabilitySurfaceRate;
198 const int surface_offset = interior_points;
199 if (surface.Size() < surface_offset + boundary_points)
201 surface.SetSize(surface_offset + boundary_points);
204 const mfem::real_t *face_state = operator_cache.uBnd.Read();
205 const mfem::real_t *normal = dc.bnd_nor_d;
206 const mfem::real_t *weight = dc.bnd_wt_d;
207 const int *boundary_marker = dc.bnd_marker_index_d;
208 const BCDescriptor *boundary_conditions = dc.bc_descr_d;
209 const mfem::real_t *boundary_data = dc.bc_vector_d;
210 mfem::real_t *surface_rate = surface.Write() + surface_offset;
211 mfem::forall(boundary_points, [=] MFEM_HOST_DEVICE (
int point)
213 const int face = point / face_points;
214 const int face_point = point % face_points;
215 const int marker = boundary_marker[face];
218 surface_rate[point] = 0.0;
221 const mfem::real_t *states = face_state
222 + face * face_points * equations;
223 mfem::real_t interior_state[
MAXEQ];
224 for (
int equation = 0; equation < equations; ++equation)
225 interior_state[equation] = states[equation * face_points + face_point];
227 mfem::real_t normal_squared = 0.0;
228 mfem::real_t normal_velocity = 0.0;
229 for (
int direction = 0; direction < dimensions; ++direction)
231 const mfem::real_t normal_component =
232 normal[point * dimensions + direction];
233 normal_squared += normal_component * normal_component;
234 normal_velocity += gas_model.
velocity(interior, direction)
237 const mfem::real_t normal_wave_speed =
239 + gas_model.sound_speed(interior) *
Kernels::rsqrt(normal_squared);
240 mfem::real_t boundary_wave_speed = normal_wave_speed;
241 const BCDescriptor &condition = boundary_conditions[marker];
245 mfem::real_t exterior_normal_velocity = 0.0;
246 for (
int direction = 0; direction < dimensions; ++direction)
247 exterior_normal_velocity += gas_model.velocity(exterior, direction)
248 * normal[point * dimensions + direction];
252 + gas_model.sound_speed(exterior) *
Kernels::rsqrt(normal_squared));
254 surface_rate[point] = boundary_wave_speed *
Kernels::rabs(weight[point])
257 const mfem::real_t *surface_host = surface.HostRead() + surface_offset;
258 for (
int point = 0; point < boundary_points; ++point)
259 estimate.surface_rate = std::max(estimate.surface_rate,
260 surface_host[point]);
513 const int nval_restr = operator_cache.restr_v->Height();
516 auto dc = device_cache;
519 const int ne = dc.num_elements;
520 const int ndof = dc.ndof_scalar_el;
521 const int neq = dc.num_equations;
522 const mfem::real_t *qWts_d = dc.elQWgts_d;
523 const mfem::real_t *radius_d = dc.elRadius_d;
526 if(operator_cache.uVol.Size() != nval_restr){
527 operator_cache.uVol.SetSize(nval_restr);
528 operator_cache.uVol.UseDevice();
530 mfem::Vector &Ue(operator_cache.uVol);
531 if(!operator_cache.u_vol_restr_ready){
532 operator_cache.restr_v->Mult(u, Ue);
533 operator_cache.u_vol_restr_ready =
true;
536 const mfem::real_t *Ue_d = Ue.Read();
537 const int estride = ndof*neq;
539 mfem::Vector elMass_integral(ne);
540 mfem::Vector elKE_integral(ne);
541 mfem::Vector elEnergy_integral(ne);
542 mfem::Vector elMaxPressure(ne);
543 mfem::Vector elMaxTemperature(ne);
544 mfem::Vector elMaxDensity(ne);
545 mfem::Vector elMinPressure(ne);
546 mfem::Vector elMinTemperature(ne);
547 mfem::Vector elMinDensity(ne);
549 elMass_integral.UseDevice();
550 elKE_integral.UseDevice();
551 elEnergy_integral.UseDevice();
552 elMaxPressure.UseDevice();
553 elMaxTemperature.UseDevice();
554 elMaxDensity.UseDevice();
555 elMinPressure.UseDevice();
556 elMinTemperature.UseDevice();
557 elMinDensity.UseDevice();
559 mfem::real_t *elMass_int_d = elMass_integral.Write();
560 mfem::real_t *elKE_int_d = elKE_integral.Write();
561 mfem::real_t *elEnergy_int_d = elEnergy_integral.Write();
563 mfem::real_t *elPress_max_d = elMaxPressure.Write();
564 mfem::real_t *elTemp_max_d = elMaxTemperature.Write();
565 mfem::real_t *elDens_max_d = elMaxDensity.Write();
566 mfem::real_t *elPress_min_d = elMinPressure.Write();
567 mfem::real_t *elTemp_min_d = elMinTemperature.Write();
568 mfem::real_t *elDens_min_d = elMinDensity.Write();
571 mfem::forall(ne, [=] MFEM_HOST_DEVICE (
int e)
573 const mfem::real_t *u_el = Ue_d + e * estride;
574 const mfem::real_t *qWgt = qWts_d + e * ndof;
575 const mfem::real_t *radius = dc.axisymmetric ?
576 radius_d + e * ndof :
nullptr;
578 mfem::real_t mass_int = 0.0;
579 mfem::real_t ke_int = 0.0;
580 mfem::real_t en_int = 0.0;
581 mfem::real_t min_dens = 1e32;
582 mfem::real_t max_dens = 0.0;
583 mfem::real_t min_temp = 1e32;
584 mfem::real_t max_temp = 0.0;
585 mfem::real_t min_press = 1e32;
586 mfem::real_t max_press = 0.0;
588 for(
int ep = 0;ep < ndof;ep++){
593 mfem::real_t rho = gas.density(S);
594 mfem::real_t ke = gas.kinetic_energy_density(S);
595 mfem::real_t rhoE = gas.
energy(S);
596 mfem::real_t press = gas.pressure(S);
597 mfem::real_t temper = gas.temperature(S);
599 const mfem::real_t measure = qWgt[ep] *
601 dc.axisymmetric, dc.axisymmetric ? radius[ep] : 0.0);
602 mass_int += rho * measure;
603 ke_int += ke * measure;
604 en_int += rhoE * measure;
614 elMass_int_d[e] = mass_int;
615 elKE_int_d[e] = ke_int;
616 elEnergy_int_d[e] = en_int;
617 elPress_max_d[e] = max_press;
618 elPress_min_d[e] = min_press;
619 elDens_max_d[e] = max_dens;
620 elDens_min_d[e] = min_dens;
621 elTemp_min_d[e] = min_temp;
622 elTemp_max_d[e] = max_temp;
639 const mfem::real_t *mass_h = elMass_integral.HostRead();
640 const mfem::real_t *ke_h = elKE_integral.HostRead();
641 const mfem::real_t *en_h = elEnergy_integral.HostRead();
642 const mfem::real_t *minpress_h = elMinPressure.HostRead();
643 const mfem::real_t *maxpress_h = elMaxPressure.HostRead();
644 const mfem::real_t *mindens_h = elMinDensity.HostRead();
645 const mfem::real_t *maxdens_h = elMaxDensity.HostRead();
646 const mfem::real_t *mintemp_h = elMinTemperature.HostRead();
647 const mfem::real_t *maxtemp_h = elMaxTemperature.HostRead();
649 for (
int e = 0; e < ne; ++e) {
650 diag.
mass += mass_h[e];
661 mfem::real_t sendbuf[3] = {diag.
mass, diag.
ke, diag.
en};
662 mfem::real_t recvbuf[3] = {0.0, 0.0, 0.0};
664 MPI_Allreduce(sendbuf, recvbuf, 3, mfem::MPITypeMap<mfem::real_t>::mpi_type, MPI_SUM, pmesh->GetComm());
666 diag.
mass = recvbuf[0];
667 diag.
ke = recvbuf[1];
668 diag.
en = recvbuf[2];
674 MPI_Allreduce(sendbuf, recvbuf, 3, mfem::MPITypeMap<mfem::real_t>::mpi_type, MPI_MIN, pmesh->GetComm());
684 MPI_Allreduce(sendbuf, recvbuf, 3, mfem::MPITypeMap<mfem::real_t>::mpi_type, MPI_MAX, pmesh->GetComm());
690 if(diag0.mass == 0.0){
700 operator_cache.u_vol_restr_ready =
false;
701 operator_cache.u_bnd_restr_ready =
false;
702 operator_cache.u_int_restr_ready =
false;
705 const mfem::Vector &pu = this->Prolongate(u);
706 FetchRestrictions(pu, operator_cache.uVol, operator_cache.uInt, operator_cache.uBnd);
709 if(operator_cache.pdudt.Size() != this->P->Height()){
710 operator_cache.pdudt.SetSize(this->P->Height());
714 mfem::Vector &pdudt = this->P ? operator_cache.pdudt : dudt;
717 int nval_restr = operator_cache.restr_v->Height();
718 if(operator_cache.uVol.Size() != nval_restr){
719 operator_cache.uVol.SetSize(nval_restr);
720 operator_cache.uVol.UseDevice();
722 mfem::Vector &Ue(operator_cache.uVol);
723 if(operator_cache.rhsVol.Size() != nval_restr){
724 operator_cache.rhsVol.SetSize(nval_restr);
725 operator_cache.rhsVol.UseDevice();
727 mfem::Vector &dUe(operator_cache.rhsVol);
729#ifdef SUBCELL_FV_BLENDING
732 const mfem::Vector &pu = this->Prolongate(u);
733 ComputeIndicatorField(pu);
734 CheckIndicatorSmoothness();
735 ComputeBlendingCoefficient();
740 int psize = pdudt.Size();
741 mfem::real_t *pdudt_d = pdudt.Write();
744 mfem::forall(psize, [=] MFEM_HOST_DEVICE (
int i) { pdudt_d[i] = 0.0; });
754 if(this->cP) this->cP->MultTranspose(pdudt, dudt);
758 if(this->P) this->P->MultTranspose(pdudt, dudt);
761 const int N = this->ess_tdof_list.Size();
762 const auto idx = this->ess_tdof_list.Read();
763 auto DU_RW = dudt.ReadWrite();
764 mfem::forall(N, [=] MFEM_HOST_DEVICE (
int i) { DU_RW[idx[i]] = 0.0; });
767 operator_cache.u_vol_restr_ready =
false;
768 operator_cache.u_bnd_restr_ready =
false;
769 operator_cache.u_int_restr_ready =
false;