diff --git a/applications/FluidDynamicsApplication/custom_elements/alternative_d_vms_dem_coupled.cpp b/applications/FluidDynamicsApplication/custom_elements/alternative_d_vms_dem_coupled.cpp index d38632405cf9..b69a9bef9ad7 100644 --- a/applications/FluidDynamicsApplication/custom_elements/alternative_d_vms_dem_coupled.cpp +++ b/applications/FluidDynamicsApplication/custom_elements/alternative_d_vms_dem_coupled.cpp @@ -24,7 +24,6 @@ namespace Kratos { - /////////////////////////////////////////////////////////////////////////////////////////////////// // Life cycle @@ -102,8 +101,11 @@ void AlternativeDVMSDEMCoupled::Calculate( Vector GaussWeights; Matrix ShapeFunctions; ShapeFunctionDerivativesArrayType ShapeDerivatives; + DenseVector> ShapeSecondDerivatives; this->CalculateGeometryData(GaussWeights,ShapeFunctions,ShapeDerivatives); const unsigned int NumGauss = GaussWeights.size(); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + ShapeSecondDerivatives,this->GetGeometry(),this->GetIntegrationMethod()); array_1d momentum_rhs = ZeroVector(NumNodes*Dim); VectorType MassRHS = ZeroVector(NumNodes); @@ -113,7 +115,7 @@ void AlternativeDVMSDEMCoupled::Calculate( data.Initialize(*this, rCurrentProcessInfo); for (unsigned int g = 0; g < NumGauss; g++) { - this->UpdateIntegrationPointData(data, g, GaussWeights[g], row(ShapeFunctions, g), ShapeDerivatives[g]); + this->UpdateIntegrationPointDataSecondDerivatives(data, g, GaussWeights[g], row(ShapeFunctions, g), ShapeDerivatives[g],ShapeSecondDerivatives[g]); array_1d MomentumRes = ZeroVector(3); double MassRes = 0.0; @@ -160,6 +162,15 @@ void AlternativeDVMSDEMCoupled::Calculate( } } +template< class TElementData > +GeometryData::IntegrationMethod AlternativeDVMSDEMCoupled::GetIntegrationMethod() const +{ + if(mInterpolationOrder == 1) + return GeometryData::IntegrationMethod::GI_GAUSS_2; + else + return GeometryData::IntegrationMethod::GI_GAUSS_3; +} + /////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// // Input and output @@ -170,11 +181,20 @@ void AlternativeDVMSDEMCoupled::Initialize(const ProcessInfo& rCur // Base class does things with constitutive law here. DVMS::Initialize(rCurrentProcessInfo); + if(Dim == 2){ + if (NumNodes == 9 || NumNodes == 6 || NumNodes == 4) + mInterpolationOrder = 2; + } + else if(Dim == 3){ + if (NumNodes == 10 || NumNodes == 27) + mInterpolationOrder = 2; + } + const unsigned int number_of_gauss_points = this->GetGeometry().IntegrationPointsNumber(this->GetIntegrationMethod()); // The prediction is updated before each non-linear iteration: // It is not stored in a restart and can be safely initialized. - mPreviousVelocity.resize(number_of_gauss_points); + //mPreviousVelocity.resize(number_of_gauss_points); // The old velocity may be already defined (if restarting) // and we want to keep the loaded values in that case. @@ -186,7 +206,7 @@ void AlternativeDVMSDEMCoupled::Initialize(const ProcessInfo& rCur } mPredictedSubscaleVelocity.resize(number_of_gauss_points); - for (unsigned int g = 0; g < number_of_gauss_points; g++) + // The old velocity may be already defined (if restarting) // and we want to keep the loaded values in that case. if (mOldSubscaleVelocity.size() != number_of_gauss_points) @@ -195,6 +215,119 @@ void AlternativeDVMSDEMCoupled::Initialize(const ProcessInfo& rCur for (unsigned int g = 0; g < number_of_gauss_points; g++) mOldSubscaleVelocity[g] = ZeroVector(Dim); } + + if (mViscousResistanceTensor.size() != number_of_gauss_points) + { + mViscousResistanceTensor.resize(number_of_gauss_points); + for (unsigned int g = 0; g < number_of_gauss_points; g++) + mViscousResistanceTensor[g] = ZeroMatrix(Dim,Dim); + } +} + +template< class TElementData > +void AlternativeDVMSDEMCoupled::CalculateOnIntegrationPoints( + const Variable& rVariable, + std::vector& rOutput, + const ProcessInfo& rCurrentProcessInfo) +{ + const GeometryType::IntegrationPointsArrayType integration_points = this->GetGeometry().IntegrationPoints(this->GetIntegrationMethod()); + const SizeType number_of_integration_points = integration_points.size(); + + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + + if (rOutput.size() != number_of_integration_points) + rOutput.resize(number_of_integration_points); + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + for (IndexType g = 0; g < number_of_integration_points; g++ ) { + data.UpdateGeometryValues(g, gauss_weights[g], row(shape_functions, g),shape_derivatives[g]); + if (rVariable == PRESSURE) { + const auto& r_pressure = data.Pressure; + double value = this->GetAtCoordinate(r_pressure,data.N); + rOutput[g] = value; + } + } +} + +template< class TElementData > +void AlternativeDVMSDEMCoupled::CalculateOnIntegrationPoints( + const Variable& rVariable, + std::vector& rValues, + const ProcessInfo& rCurrentProcessInfo) +{ + const GeometryType::IntegrationPointsArrayType integration_points = this->GetGeometry().IntegrationPoints(this->GetIntegrationMethod()); + const SizeType number_of_integration_points = integration_points.size(); + + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + + if (rValues.size() != number_of_integration_points) + rValues.resize(number_of_integration_points); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + for (IndexType g = 0; g < number_of_integration_points; ++g ) { + data.UpdateGeometryValues(g, gauss_weights[g], row(shape_functions, g),shape_derivatives[g]); + Matrix value = ZeroMatrix(Dim, Dim); + if (rVariable == VELOCITY_GRADIENT) { + const auto& r_velocity = data.Velocity; + for (IndexType i = 0; i < NumNodes; ++i) { + for (IndexType d = 0; d < Dim; ++d) { + for (IndexType e = 0; e < Dim; ++e) + value(d,e) += data.DN_DX(i,d) * r_velocity(i,e); + } + } + } + rValues[g] = value; + } +} + +template< class TElementData > +void AlternativeDVMSDEMCoupled::CalculateOnIntegrationPoints( + const Variable>& rVariable, + std::vector>& rOutput, + const ProcessInfo& rCurrentProcessInfo) +{ + const GeometryType::IntegrationPointsArrayType integration_points = this->GetGeometry().IntegrationPoints(this->GetIntegrationMethod()); + const SizeType number_of_integration_points = integration_points.size(); + + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + + if (rOutput.size() != number_of_integration_points) + rOutput.resize(number_of_integration_points); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + for (unsigned int g = 0; g < number_of_integration_points; g++ ) { + data.UpdateGeometryValues(g, gauss_weights[g], row(shape_functions, g),shape_derivatives[g]); + array_1d value(3, 0.0); + if (rVariable == VELOCITY) { + const auto& r_velocity = data.Velocity; + value = this->GetAtCoordinate(r_velocity,data.N); + } + if (rVariable == PRESSURE_GRADIENT){ + const auto& r_pressure = data.Pressure; + for (unsigned int i = 0; i < NumNodes; i++) { + for (unsigned int d = 0; d < Dim; d++) { + value[d] += r_pressure[i] * data.DN_DX(i,d); + } + } + } + rOutput[g] = value; + } } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -206,14 +339,17 @@ void AlternativeDVMSDEMCoupled::FinalizeSolutionStep(const Process Vector gauss_weights; Matrix shape_functions; ShapeFunctionDerivativesArrayType shape_function_derivatives; + DenseVector> shape_function_second_derivatives; this->CalculateGeometryData(gauss_weights,shape_functions,shape_function_derivatives); const unsigned int number_of_integration_points = gauss_weights.size(); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); TElementData data; data.Initialize(*this,rCurrentProcessInfo); array_1d UpdatedValue; for (unsigned int g = 0; g < number_of_integration_points; g++) { - this->UpdateIntegrationPointData(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g]); + this->UpdateIntegrationPointDataSecondDerivatives(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g],shape_function_second_derivatives[g]); // Not doing the update "in place" because SubscaleVelocity uses mOldSubscaleVelocity UpdatedValue = ZeroVector(3); @@ -232,13 +368,18 @@ void AlternativeDVMSDEMCoupled::InitializeNonLinearIteration(const Vector gauss_weights; Matrix shape_functions; ShapeFunctionDerivativesArrayType shape_function_derivatives; + DenseVector> shape_function_second_derivatives; this->CalculateGeometryData(gauss_weights,shape_functions,shape_function_derivatives); const unsigned int number_of_integration_points = gauss_weights.size(); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); TElementData data; data.Initialize(*this,rCurrentProcessInfo); for (unsigned int g = 0; g < number_of_integration_points; g++) { - this->UpdateIntegrationPointData(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g]); + this->UpdateIntegrationPointDataSecondDerivatives(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g],shape_function_second_derivatives[g]); + + this->CalculateResistanceTensor(data); } } @@ -249,18 +390,34 @@ void AlternativeDVMSDEMCoupled::FinalizeNonLinearIteration(const P Vector gauss_weights; Matrix shape_functions; ShapeFunctionDerivativesArrayType shape_function_derivatives; + DenseVector> shape_function_second_derivatives; this->CalculateGeometryData(gauss_weights,shape_functions,shape_function_derivatives); const unsigned int number_of_integration_points = gauss_weights.size(); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); TElementData data; data.Initialize(*this,rCurrentProcessInfo); for (unsigned int g = 0; g < number_of_integration_points; g++) { - this->UpdateIntegrationPointData(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g]); + this->UpdateIntegrationPointDataSecondDerivatives(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g],shape_function_second_derivatives[g]); this->UpdateSubscaleVelocity(data); } } +template +void AlternativeDVMSDEMCoupled::UpdateIntegrationPointDataSecondDerivatives( + TElementData& rData, + unsigned int IntegrationPointIndex, + double Weight, + const typename TElementData::MatrixRowType& rN, + const typename TElementData::ShapeDerivativesType& rDN_DX, + const typename TElementData::ShapeFunctionsSecondDerivativesType& rDDN_DDX) const +{ + this->UpdateIntegrationPointData(rData, IntegrationPointIndex, Weight, rN, rDN_DX); + rData.UpdateSecondDerivativesValues(rDDN_DDX); +} + template< class TElementData > std::string AlternativeDVMSDEMCoupled::Info() const { @@ -296,36 +453,40 @@ void AlternativeDVMSDEMCoupled::AlgebraicMomentumResidual( const double density = this->GetAtCoordinate(rData.Density,rData.N); const double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); - - const auto& r_body_forces = rData.BodyForce; + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; + const auto& body_force = this->GetAtCoordinate(rData.BodyForce, rData.N); const auto& r_velocities = rData.Velocity; const auto& r_pressures = rData.Pressure; - const auto& r_fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); + const auto& fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - sigma *= viscosity; - Vector sigma_U, grad_alpha_sym_grad_u; + Vector sigma_U, grad_alpha_sym_grad_u, grad_div_u, div_sym_grad_u; BoundedMatrix sym_gradient_u; + for (unsigned int i = 0; i < NumNodes; i++) { const array_1d& r_acceleration = rGeom[i].FastGetSolutionStepValue(ACCELERATION); sigma_U = ZeroVector(Dim); + grad_div_u = ZeroVector(Dim); sym_gradient_u = ZeroMatrix(Dim, Dim); grad_alpha_sym_grad_u = ZeroVector(Dim); + div_sym_grad_u = ZeroVector(Dim); for (unsigned int d = 0; d < Dim; d++) { double div_u = 0.0; for (unsigned int e = 0; e < Dim; e++){ sigma_U[d] += sigma(d,e) * rData.N[i] * r_velocities(i,e); sym_gradient_u(d,e) += 1.0 / 2.0 * (rData.DN_DX(i,d) * r_velocities(i,e) + rData.DN_DX(i,e) * r_velocities(i,d)); - grad_alpha_sym_grad_u[d] += r_fluid_fraction_gradient[d] * sym_gradient_u(d,e); + grad_alpha_sym_grad_u[d] += fluid_fraction_gradient[e] * sym_gradient_u(d,e); div_u += rData.DN_DX(i,e) * r_velocities(i,e); + grad_div_u[d] += rData.DDN_DDX[i](d,e) * r_velocities(i,e); + if (d == e) + div_sym_grad_u[d] += rData.DDN_DDX[i](e,e) * r_velocities(i,d); + else + div_sym_grad_u[d] += 1.0/2.0 * (rData.DDN_DDX[i](e,d) * r_velocities(i,e) + rData.DDN_DDX[i](e,e) * r_velocities(i,d)); } - rResidual[d] += density * (rData.N[i] * r_body_forces(i,d) - fluid_fraction * rData.N[i] * r_acceleration[d] - fluid_fraction * convection[i] * r_velocities(i,d)) + 2 * grad_alpha_sym_grad_u[d] * viscosity - 2.0 / 3.0 * viscosity * r_fluid_fraction_gradient[d] * div_u - fluid_fraction * rData.DN_DX(i,d) * r_pressures[i] - sigma_U[d]; + rResidual[d] += density * (- fluid_fraction * rData.N[i] * r_acceleration[d] - fluid_fraction * convection[i] * r_velocities(i,d)) + 2.0 * grad_alpha_sym_grad_u[d] * viscosity - 2.0 / 3.0 * viscosity * fluid_fraction_gradient[d] * div_u + 2.0 * fluid_fraction * viscosity * div_sym_grad_u[d] - 2.0/3.0 * fluid_fraction * viscosity * grad_div_u[d] - fluid_fraction * rData.DN_DX(i,d) * r_pressures[i] - sigma_U[d]; } } + for (unsigned int d = 0; d < Dim; d++) + rResidual[d] += density * body_force[d]; } template< class TElementData > @@ -334,62 +495,63 @@ void AlternativeDVMSDEMCoupled::MomentumProjTerm( const array_1d& rConvectionVelocity, array_1d &rMomentumRHS) const { + //const auto& rGeom = this->GetGeometry(); + Vector AGradN; this->ConvectionOperator(AGradN,rConvectionVelocity,rData.DN_DX); const double density = this->GetAtCoordinate(rData.Density,rData.N); const double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); - - sigma *= viscosity; - + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; const auto& fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); - - sigma *= viscosity; - Vector grad_alpha_sym_grad_u; - array_1d sigma_u; + const auto& body_force = this->GetAtCoordinate(rData.BodyForce, rData.N); + Vector grad_alpha_sym_grad_u, grad_div_u, sigma_U, div_sym_grad_u; + BoundedMatrix sym_gradient_u; for (unsigned int i = 0; i < NumNodes; i++) { - sigma_u = ZeroVector(Dim); - BoundedMatrix sym_gradient_u = ZeroMatrix(Dim, Dim); + + grad_div_u = ZeroVector(Dim); + sym_gradient_u = ZeroMatrix(Dim, Dim); grad_alpha_sym_grad_u = ZeroVector(Dim); + div_sym_grad_u = ZeroVector(Dim); for (unsigned int d = 0; d < Dim; d++) { double div_u = 0.0; for (unsigned int e = 0; e < Dim; e++){ - sigma_u[d] += sigma(d,e) * rData.N[i] * rData.Velocity(i,e); sym_gradient_u(d,e) += 1.0 / 2.0 * (rData.DN_DX(i,d) * rData.Velocity(i,e) + rData.DN_DX(i,e) * rData.Velocity(i,d)); - grad_alpha_sym_grad_u[d] += fluid_fraction_gradient[d] * sym_gradient_u(d,e); + grad_alpha_sym_grad_u[d] += fluid_fraction_gradient[e] * sym_gradient_u(d,e); div_u += rData.DN_DX(i,e) * rData.Velocity(i,e); + grad_div_u[d] += rData.DDN_DDX[i](d,e) * rData.Velocity(i,e); + if (d == e) + div_sym_grad_u[d] += rData.DDN_DDX[i](e,e) * rData.Velocity(i,d); + else + div_sym_grad_u[d] += 1.0/2.0 * (rData.DDN_DDX[i](e,d) * rData.Velocity(i,e) + rData.DDN_DDX[i](e,e) * rData.Velocity(i,d)); } - rMomentumRHS[d] += density * ( rData.N[i] * (rData.BodyForce(i,d)) /*- fluid_fraction * rData.N[i] * rAcc[d]*/ - - fluid_fraction * AGradN[i] * rData.Velocity(i,d)) + 2 * grad_alpha_sym_grad_u[d] * viscosity - 2.0 / 3.0 * viscosity * fluid_fraction_gradient[d] * div_u - fluid_fraction * rData.DN_DX(i,d)*rData.Pressure[i] - sigma_u[d]; + rMomentumRHS[d] += density * (- fluid_fraction * AGradN[i] * rData.Velocity(i,d)) + 2.0 * grad_alpha_sym_grad_u[d] * viscosity - 2.0/3.0 * viscosity * fluid_fraction_gradient[d] * div_u + 2.0 * fluid_fraction * viscosity * div_sym_grad_u[d] - 2.0/3.0 * fluid_fraction * viscosity * grad_div_u[d] - fluid_fraction * rData.DN_DX(i,d) * rData.Pressure[i]/* - sigma_U[d]*/; } } + for (unsigned int d = 0; d < Dim; d++) + rMomentumRHS[d] += density * body_force[d]; } +// Add a the contribution from a single integration point to the velocity contribution template< class TElementData > void AlternativeDVMSDEMCoupled::AddVelocitySystem( TElementData& rData, MatrixType &rLocalLHS, VectorType &rLocalRHS) { - auto& LHS = rData.LHS; + BoundedMatrix& LHS = rData.LHS; LHS.clear(); const double density = this->GetAtCoordinate(rData.Density,rData.N); const array_1d body_force = density * this->GetAtCoordinate(rData.BodyForce,rData.N); - const array_1d convective_velocity = this->FullConvectiveVelocity(rData); array_1d velocity = this->GetAtCoordinate(rData.Velocity,rData.N); array_1d& r_prev_velocity = mPreviousVelocity[rData.IntegrationPointIndex]; - for (unsigned int n = 0; n < Dim; n++){ + + for (unsigned int n = 0; n < Dim; n++) r_prev_velocity[n] = velocity[n]; - } BoundedMatrix tau_one = ZeroMatrix(Dim, Dim); double tau_two; @@ -410,18 +572,14 @@ void AlternativeDVMSDEMCoupled::AddVelocitySystem( // Multiplying convective operator by density to have correct units AGradN *= density; - double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); - double kin_viscosity = viscosity / density; + const double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); const double fluid_fraction_rate = this->GetAtCoordinate(rData.FluidFractionRate, rData.N); const double mass_source = this->GetAtCoordinate(rData.MassSource, rData.N); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); - array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); + //BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - sigma *= viscosity; // Multiplying convective operator by density to have correct units // Note: Dof order is (u,v,[w,]p) for each node for (unsigned int i = 0; i < NumNodes; i++) { @@ -435,7 +593,6 @@ void AlternativeDVMSDEMCoupled::AddVelocitySystem( // Some terms are the same for all velocity components, calculate them once for each i,j // Skew-symmetric convective term 1/2( v*grad(u)*u - grad(v) uu ) - //double K = 0.5*(rN[i]*AGradN[j] - AGradN[i]*rN[j]); double V = fluid_fraction * rData.N[i] * AGradN[j]; // q-p stabilization block (reset result) @@ -447,11 +604,7 @@ void AlternativeDVMSDEMCoupled::AddVelocitySystem( double A = tau_one(d,d) * density * std::pow(fluid_fraction, 2) * rData.N[i]/dt * AGradN[j]; - double GBetaDiag = tau_one(d,d) * fluid_fraction * kin_viscosity * rData.N[i] / dt * rData.DN_DX(j,d) * fluid_fraction_gradient[d]; - double AGBetaDiag = tau_one(d,d) * fluid_fraction * kin_viscosity * AGradN[i] * (rData.DN_DX(j,d) * fluid_fraction_gradient[d]); - double GBetaADiag = tau_one(d,d) * fluid_fraction * kin_viscosity * fluid_fraction_gradient[d] * rData.DN_DX(i,d) * AGradN[j]; - - LHS(row+d,col+d) += rData.Weight * (V + AA - A + GBetaDiag - AGBetaDiag + GBetaADiag); + LHS(row+d,col+d) += rData.Weight * (V + AA - A); // Galerkin pressure term: Div(v) * p double P = fluid_fraction * rData.DN_DX(i,d) * rData.N[j]; @@ -459,82 +612,170 @@ void AlternativeDVMSDEMCoupled::AddVelocitySystem( double GP = fluid_fraction_gradient[d] * rData.N[j] * rData.N[i]; - double GD = fluid_fraction_gradient[d] * rData.N[j] * rData.N[i]; + double GAlphaD = fluid_fraction_gradient[d] * rData.N[j] * rData.N[i]; /* q-p stabilization block */ // Stabilization: Grad(q) * TauOne * Grad(p) G += tau_one(d,d) * fluid_fraction * fluid_fraction * rData.DN_DX(i,d) * rData.DN_DX(j,d); /* v-u block */ // Stabilization: Div(v) * TauTwo * Div(u) - double GR = 0.0; - double RSigmaG = 0.0; - double GG = 0.0; + double GG_1 = 0.0; + double GG_2 = 0.0; double DG = 0.0; - double GGBeta = 0.0; - double GDBeta = 0.0; - double GA = tau_one(d,d) * fluid_fraction * fluid_fraction * rData.DN_DX(i,d) * AGradN[j]; + double GGBeta_1 = 0.0; + double GGBeta_2 = 0.0; + double GC = 0.0; + double CG = 0.0; + double GL = 0.0; + double LG = 0.0; // Stabilization: (a * Grad(v)) * TauOne * Grad(p) - double AG = fluid_fraction * fluid_fraction * tau_one(d,d) * AGradN[i] * rData.DN_DX(j,d); + double AG = tau_one(d,d) * fluid_fraction * fluid_fraction * AGradN[i] * rData.DN_DX(j,d); + double GA = tau_one(d,d) * fluid_fraction * fluid_fraction * rData.DN_DX(i,d) * AGradN[j]; // From vh*d(u_ss)/dt: vh * TauOne/Dt * Grad(p) - double VP = tau_one(d,d) * density * rData.N[i] / dt * rData.DN_DX(j,d) * fluid_fraction * fluid_fraction; + double VP = tau_one(d,d) * density * fluid_fraction * fluid_fraction * rData.N[i] / dt * rData.DN_DX(j,d); + double GDBeta = 0.0; for (unsigned int e = 0; e < Dim; e++){ - double GBetaGDiag = tau_one(d,d) * std::pow(kin_viscosity, 2) * fluid_fraction_gradient[d] * rData.DN_DX(i,d) * (rData.DN_DX(j,e) * fluid_fraction_gradient[e]); - GGBeta += tau_one(d,d) * fluid_fraction * kin_viscosity * (rData.DN_DX(i,e) * rData.DN_DX(j,e) * fluid_fraction_gradient[d]); - GGBeta += tau_one(d,d) * fluid_fraction * kin_viscosity * (rData.DN_DX(i,d) * fluid_fraction_gradient[e] * rData.DN_DX(j,e)); - GDBeta += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * kin_viscosity * fluid_fraction_gradient[e] * rData.DN_DX(i,e) * rData.DN_DX(j,d); + double DnuD = 2.0/3.0 * fluid_fraction * viscosity * rData.DN_DX(i,d) * rData.DN_DX(j,e); + double GS = fluid_fraction * viscosity * rData.DN_DX(i,e) * rData.DN_DX(j,d); + double L = tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * density * rData.N[i]/dt * rData.DDN_DDX[j](d,e); + double C = 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * density * rData.N[i]/dt * rData.DDN_DDX[j](d,e); + GDBeta += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * fluid_fraction_gradient[e] * rData.DN_DX(i,e) * rData.DN_DX(j,d); + GL += tau_one(d,d) * viscosity * std::pow(fluid_fraction,2) * rData.DN_DX(i,e) * rData.DDN_DDX[j](d,e); + GL += tau_one(d,d) * viscosity * std::pow(fluid_fraction,2) * rData.DN_DX(i,d) * rData.DDN_DDX[j](e,e); + GGBeta_1 += tau_one(d,d) * fluid_fraction * viscosity * rData.DN_DX(i,e) * rData.DN_DX(j,e) * fluid_fraction_gradient[d]; + GGBeta_2 += tau_one(d,d) * fluid_fraction * viscosity * rData.DN_DX(i,d) * rData.DN_DX(j,e) * fluid_fraction_gradient[e]; + GG_1 += tau_one(d,d) * fluid_fraction * viscosity * fluid_fraction_gradient[d] * rData.DN_DX(i,e) * rData.DN_DX(j,e); + GG_2 += tau_one(d,d) * fluid_fraction * viscosity * fluid_fraction_gradient[e] * rData.DN_DX(i,e) * rData.DN_DX(j,d); + LG += tau_one(d,d) * viscosity * std::pow(fluid_fraction,2) * rData.DN_DX(j,e) * rData.DDN_DDX[i](d,e); + LG += tau_one(d,d) * viscosity * std::pow(fluid_fraction,2) * rData.DN_DX(j,d) * rData.DDN_DDX[i](e,e); + GC += 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DN_DX(i,e) * rData.DDN_DDX[j](e,d); + CG += 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[i](d,e) * rData.DN_DX(j,e); + DG += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * rData.DN_DX(i,d) * fluid_fraction_gradient[e] * rData.DN_DX(j,e); + double AL = tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * AGradN[i] * rData.DDN_DDX[j](d,e); + double LA = tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[i](d,e) * AGradN[j]; + double AC = 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * AGradN[i] * rData.DDN_DDX[j](d,e); + double CA = 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[i](d,e) * AGradN[j]; + double DBetaA = 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * AGradN[j] * fluid_fraction_gradient[e] * rData.DN_DX(i,d); double RSigma = rData.N[i] * sigma(d,e) * rData.N[j]; - double VSigma = tau_one(d,d) * fluid_fraction * density/dt * rData.N[i] * rData.N[j] * sigma(d,e); - double ASigma = tau_one(d,d) * AGradN[i] * sigma(d,e) * rData.N[j] * fluid_fraction; - double ADBeta = 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * kin_viscosity * AGradN[i] * fluid_fraction_gradient[d] * rData.DN_DX(j,e); - double RRSigma = tau_one(d,d) * sigma(d,e) * rData.N[i] * sigma(e,d) * rData.N[j]; - double RSigmaA = tau_one(d,d) * fluid_fraction * sigma(d,e) * rData.N[i] * AGradN[j]; - double DD = tau_two * fluid_fraction * fluid_fraction * rData.DN_DX(i,d) * rData.DN_DX(j,e); + double AGBeta = tau_one(d,d) * fluid_fraction * viscosity * AGradN[i] * rData.DN_DX(j,d) * fluid_fraction_gradient[e]; + double ADBeta = 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * AGradN[i] * fluid_fraction_gradient[d] * rData.DN_DX(j,e); + double DD = tau_two * std::pow(fluid_fraction,2) * rData.DN_DX(i,d) * rData.DN_DX(j,e); double DU = tau_two * fluid_fraction * fluid_fraction_gradient[e] * rData.DN_DX(i,d) * rData.N[j]; - double DBeta = 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * kin_viscosity * rData.N[i] / dt * fluid_fraction_gradient[d] * rData.DN_DX(j,e); - double DBetaA = 2.0 /3.0 * kin_viscosity * fluid_fraction * tau_one(d,d) * AGradN[j] * fluid_fraction_gradient[e] * rData.DN_DX(i,d); + double GD = tau_two * fluid_fraction * fluid_fraction_gradient[d] * rData.DN_DX(j,e) * rData.N[i]; double GU = tau_two * rData.N[j] * rData.N[i] * fluid_fraction_gradient[d] * fluid_fraction_gradient[e]; - double GD = tau_two * fluid_fraction * rData.N[i] * fluid_fraction_gradient[d] * rData.DN_DX(j,e); - double GBeta = tau_one(d,d) * fluid_fraction * kin_viscosity * rData.N[i] / dt * (rData.DN_DX(j,d) * fluid_fraction_gradient[e]); - double AGBeta = tau_one(d,d) * fluid_fraction * kin_viscosity * AGradN[i] * (rData.DN_DX(j,d) * fluid_fraction_gradient[e]); - double GBetaA = tau_one(d,d) * fluid_fraction * kin_viscosity * AGradN[j] * rData.DN_DX(i,e) * fluid_fraction_gradient[d]; - double GBetaG = 0.0; - double GBetaD = 0.0; - double GBetaSigma = 0.0; + double GBetaA = tau_one(d,d) * fluid_fraction * viscosity * AGradN[j] * fluid_fraction_gradient[d] * rData.DN_DX(i,e); + double LL_diag_1 = 0.0; + double LL_diag_2 = 0.0; + double LL_2 = 0.0; + double LL_3 = 0.0; + double LL_4 = 0.0; + double LC_1 = 0.0; + double LC_2 = 0.0; + double LGBeta_1 = 0.0; + double LGBeta_2 = 0.0; + double LGBeta_3 = 0.0; + double LGBeta_4 = 0.0; + double LGBeta_5 = 0.0; + double LDBeta_1 = 0.0; + double LDBeta_2 = 0.0; + double CL_1 = 0.0; + double CL_2 = 0.0; + double CC = 0.0; + double CGBeta_1 = 0.0; + double CGBeta_2 = 0.0; + double CDBeta = 0.0; + double GBetaL_1 = 0.0; + double GBetaL_2 = 0.0; + double GBetaL_3 = 0.0; + double GBetaL_4 = 0.0; + double GBetaL_5 = 0.0; + double GBetaC_1 = 0.0; + double GBetaC_2 = 0.0; + double GBetaG_1 = 0.0; + double GBetaG_2 = 0.0; + double GBetaG_3 = 0.0; + double GBetaG_4 = 0.0; + double GBetaG_5 = 0.0; + double GBetaD_1 = 0.0; + double GBetaD_2 = 0.0; + double DBetaL_1 = 0.0; + double DBetaL_2 = 0.0; + double DBetaC = 0.0; double DBetaG = 0.0; double DBetaD = 0.0; - double DBetaSigma = 0.0; - double RGBeta = 0.0; - double RDBeta = 0.0; - GG += tau_one(d,d) * fluid_fraction * kin_viscosity * (fluid_fraction_gradient[d] * rData.DN_DX(i,e) * rData.DN_DX(j,e) + fluid_fraction_gradient[e] * rData.DN_DX(i,e) * rData.DN_DX(j,d)); - DG += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * kin_viscosity * rData.DN_DX(i,d) * fluid_fraction_gradient[e] * rData.DN_DX(j,e); + double DBeta = 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * rData.N[i] / dt * fluid_fraction_gradient[d] * rData.DN_DX(j,e); + double GBeta = tau_one(d,d) * fluid_fraction * viscosity * rData.N[i]/dt * fluid_fraction_gradient[e] * rData.DN_DX(j,d); for (unsigned int f = 0; f < Dim; f++){ - GBetaG += tau_one(d,d) * std::pow(kin_viscosity, 2) * fluid_fraction_gradient[d] * (rData.DN_DX(i,f) * rData.DN_DX(j,f) * fluid_fraction_gradient[e]); - GBetaG += tau_one(d,d) * std::pow(kin_viscosity, 2) * fluid_fraction_gradient[d] * (rData.DN_DX(j,f) * rData.DN_DX(i,e) * fluid_fraction_gradient[f]); - GBetaG += tau_one(d,d) * std::pow(kin_viscosity, 2) * fluid_fraction_gradient[f] * rData.DN_DX(i,f) * (rData.DN_DX(j,d) * fluid_fraction_gradient[e]); - GBetaD += 2.0 * (2.0 / 3.0 * tau_one(d,d) * std::pow(kin_viscosity, 2) * (fluid_fraction_gradient[f] * rData.DN_DX(i,f)) * fluid_fraction_gradient[d] * rData.DN_DX(j,e)); - DBetaG += 4.0 / 3.0 * tau_one(d,d) * std::pow(kin_viscosity, 2) * rData.DN_DX(i,d) * fluid_fraction_gradient[f] * rData.DN_DX(j,f) * fluid_fraction_gradient[e]; - DBetaD += 4.0 / 9.0 * tau_one(d,d) * std::pow(kin_viscosity, 2) * fluid_fraction_gradient[f] * fluid_fraction_gradient[f] * rData.DN_DX(i,d) * rData.DN_DX(j,e); - DBetaSigma += 2.0 / 3.0 * tau_one(d,d) * kin_viscosity * rData.DN_DX(i,d) * rData.N[j] * fluid_fraction_gradient[f] * sigma(f,e); - RDBeta += 2.0 / 3.0 * tau_one(d,d) * kin_viscosity * rData.N[i] * sigma(d,f) * fluid_fraction_gradient[f] * rData.DN_DX(j,e); - for (unsigned int g = 0; g < Dim; g++){ - GBetaSigma += tau_one(d,d) * kin_viscosity * (fluid_fraction_gradient[g] * rData.DN_DX(i,f) * sigma(f,e) + fluid_fraction_gradient[g] * rData.DN_DX(i,g) * sigma(d,f)); - for(unsigned int h = 0; h < Dim; h++){ - RGBeta += tau_one(d,d) * kin_viscosity * (rData.N[d] * sigma(d,f) * rData.DN_DX(i,f) * fluid_fraction_gradient[e] + rData.N[d] * fluid_fraction_gradient[h] * rData.DN_DX(i,h) * sigma(d,e)); - } + if(d == e){ + GBetaA += tau_one(d,d) * fluid_fraction * viscosity * AGradN[j] * fluid_fraction_gradient[f] * rData.DN_DX(i,f); + GBeta += tau_one(d,d) * fluid_fraction * viscosity * rData.N[i]/dt * fluid_fraction_gradient[f] * rData.DN_DX(j,f); + AGBeta += tau_one(d,d) * fluid_fraction * viscosity * AGradN[i] * fluid_fraction_gradient[f] * rData.DN_DX(j,f); + GS += fluid_fraction * viscosity * rData.DN_DX(i,f) * rData.DN_DX(j,f); + AL += tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[j](f,f) * AGradN[i]; + LA += tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[i](f,f) * AGradN[j]; + LL_diag_1 += tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](f,f); + LL_diag_2 += rData.DDN_DDX[j](f,f); + LGBeta_3 += rData.DN_DX(j,f) * fluid_fraction_gradient[f]; + GBetaG_5 += rData.DN_DX(j,f) * fluid_fraction_gradient[f]; + GBetaL_5 += rData.DDN_DDX[j](f,f); + L += tau_one(d,d) * density * std::pow(fluid_fraction,2) * viscosity * rData.N[i]/dt * rData.DDN_DDX[j](f,f); } + LL_2 += tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](f,f) * rData.DDN_DDX[j](d,e); + LL_3 += tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](d,e) * rData.DDN_DDX[j](f,f); + LL_4 += tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](d,f) * rData.DDN_DDX[j](e,f); + LC_1 += 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](f,f) * rData.DDN_DDX[j](d,e); + LC_2 += 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](d,f) * rData.DDN_DDX[j](f,e); + CL_1 += 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](d,e) * rData.DDN_DDX[j](f,f); + CL_2 += 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](d,f) * rData.DDN_DDX[j](f,e); + CC += 4.0 / 9.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](f,d) * rData.DDN_DDX[j](f,e); + LGBeta_1 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DDN_DDX[i](f,f) * rData.DN_DX(j,d) * fluid_fraction_gradient[e]; + LGBeta_2 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DDN_DDX[i](f,f); + LGBeta_4 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DDN_DDX[i](d,f) * rData.DN_DX(j,f) * fluid_fraction_gradient[e]; + LGBeta_5 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DDN_DDX[i](d,e) * fluid_fraction_gradient[f] * rData.DN_DX(j,f); + LDBeta_1 += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DN_DX(j,e) * fluid_fraction_gradient[f] * rData.DDN_DDX[i](d,f); + LDBeta_2 += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DN_DX(j,e) * fluid_fraction_gradient[d] * rData.DDN_DDX[i](f,f); + CGBeta_1 += 2.0 /3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DDN_DDX[i](d,f) * rData.DN_DX(j,f) * fluid_fraction_gradient[e]; + CGBeta_2 += 2.0 /3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DDN_DDX[i](d,e) * rData.DN_DX(j,f) * fluid_fraction_gradient[f]; + CDBeta += 4.0 / 9.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * fluid_fraction_gradient[f] * rData.DDN_DDX[i](d,f) * rData.DN_DX(j,e); + GBetaL_1 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * fluid_fraction_gradient[d] * rData.DN_DX(i,f) * rData.DDN_DDX[j](f,e); + GBetaL_2 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * fluid_fraction_gradient[d] * rData.DN_DX(i,e) * rData.DDN_DDX[j](f,f); + GBetaL_3 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * fluid_fraction_gradient[f] * rData.DN_DX(i,f) * rData.DDN_DDX[j](d,e); + GBetaL_4 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * fluid_fraction_gradient[f] * rData.DN_DX(i,f); + GBetaC_1 += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * fluid_fraction_gradient[d] * rData.DN_DX(i,f) * rData.DDN_DDX[j](f,e); + GBetaC_2 += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * fluid_fraction_gradient[f] * rData.DN_DX(i,f) * rData.DDN_DDX[j](d,e); + DBetaL_1 += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DN_DX(i,d) * (fluid_fraction_gradient[e] * rData.DDN_DDX[j](f,f)); + DBetaL_2 += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DN_DX(i,d) * (fluid_fraction_gradient[f] * rData.DDN_DDX[j](f,e)); + DBetaC += 4.0 / 9.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DN_DX(i,d) * fluid_fraction_gradient[f] * rData.DDN_DDX[j](e,f); + DBetaG += 4.0 / 3.0 * tau_one(d,d) * std::pow(viscosity, 2) * rData.DN_DX(i,d) * fluid_fraction_gradient[f] * rData.DN_DX(j,f) * fluid_fraction_gradient[e]; + GBetaG_1 += tau_one(d,d) * std::pow(viscosity,2) * fluid_fraction_gradient[d] * rData.DN_DX(i,f) * rData.DN_DX(j,f) * fluid_fraction_gradient[e]; + GBetaG_2 += tau_one(d,d) * std::pow(viscosity,2) * fluid_fraction_gradient[d] * rData.DN_DX(i,e) * rData.DN_DX(j,f) * fluid_fraction_gradient[f]; + GBetaG_3 += tau_one(d,d) * std::pow(viscosity,2) * fluid_fraction_gradient[f] * rData.DN_DX(i,f) * rData.DN_DX(j,d) * fluid_fraction_gradient[e]; + GBetaG_4 += tau_one(d,d) * std::pow(viscosity,2) * fluid_fraction_gradient[f] * rData.DN_DX(i,f); + GBetaD_1 += 2.0 / 3.0 * tau_one(d,d) * std::pow(viscosity,2) * fluid_fraction_gradient[d] * rData.DN_DX(j,e) * fluid_fraction_gradient[f] * rData.DN_DX(i,f); + GBetaD_2 += 2.0 / 3.0 * tau_one(d,d) * std::pow(viscosity,2) * fluid_fraction_gradient[d] * rData.DN_DX(j,e) * fluid_fraction_gradient[f] * rData.DN_DX(i,f); + DBetaD += 4.0 / 9.0 * tau_one(d,d) * std::pow(viscosity, 2) * fluid_fraction_gradient[f] * fluid_fraction_gradient[f] * rData.DN_DX(i,d) * rData.DN_DX(j,e); } + double LL = (LL_diag_1*LL_diag_2) + LL_2 + LL_3 + LL_4; + double LGBeta = LGBeta_1 + (LGBeta_2 * LGBeta_3) + LGBeta_4 + LGBeta_5; + double LC = LC_1 + LC_2; + double CL = CL_1 + CL_2; + double LDBeta = LDBeta_1 + LDBeta_2; + double CGBeta = CGBeta_1 + CGBeta_2; + double GBetaL = GBetaL_1 + GBetaL_2 + GBetaL_3 + (GBetaL_4 * GBetaL_5); + double GBetaC = GBetaC_1 + GBetaC_2; + double DBetaL = DBetaL_1 + DBetaL_2; + double GBetaG = GBetaG_1 + GBetaG_2 + GBetaG_3 + (GBetaG_4*GBetaG_5); + double GBetaD = GBetaD_1 + GBetaD_2; + + LHS(row+d,col+e) += rData.Weight * (L - C + GBeta - DBeta + GS - DnuD + DD + DU + GU + GD + GBetaA - GBetaG + GBetaD - DBetaA + DBetaG - DBetaD - AGBeta + ADBeta + RSigma - AL + LA + AC - CA + LC + CL - CC - LL - LGBeta + LDBeta + CGBeta - CDBeta - GBetaL + GBetaC + DBetaL - DBetaC); - GR += tau_one(d,d) * fluid_fraction * rData.DN_DX(i,d) * sigma(d,e) * rData.N[j]; - RSigmaG += tau_one(d,d) * sigma(d,e) * rData.N[i] * rData.DN_DX(j,e); - LHS(row+d,col+e) += rData.Weight * (GBeta - DBeta + DD + DU + GU + GD + GBetaA - GBetaG + GBetaD + GBetaSigma - DBetaA + DBetaG - DBetaD - AGBeta + ADBeta - DBetaSigma + RGBeta - RDBeta + RSigma - VSigma + ASigma - RRSigma - RSigmaA); - if (d == e){ - LHS(row+d,col+e) -= rData.Weight * (GBetaGDiag); - } } + double GGBeta = GGBeta_1 + GGBeta_2; + double GG = GG_1 + GG_2; - LHS(row+Dim,col+d) += rData.Weight * (GA + QD + GR - GGBeta + GDBeta + GD); + LHS(row+Dim,col+d) += rData.Weight * (GA - GL + GC + QD - GGBeta + GDBeta + GAlphaD); - LHS(row+d,col+Dim) += rData.Weight * (AG - VP - P - GP - RSigmaG + GG - DG); + LHS(row+d,col+Dim) += rData.Weight * (AG + LG - CG - VP - P - GP + GG - DG); } @@ -548,47 +789,138 @@ void AlternativeDVMSDEMCoupled::AddVelocitySystem( { // v*BodyForce + v * du_ss/dt double VF = rData.N[i] * (body_force[d] + OldUssTerm[d]); + double VPhi = 0.0; // ( a * Grad(v) ) * TauOne * (Density * BodyForce - Projection) // vh * TauOne/Dt * f (from vh*d(uss)/dt double VI = tau_one(d,d) * density * fluid_fraction * rData.N[i] / dt * (body_force[d] - MomentumProj[d] + OldUssTerm[d]); double AF = tau_one(d,d) * fluid_fraction * AGradN[i] * (body_force[d] - MomentumProj[d] + OldUssTerm[d]); - double RSigmaF = 0.0; + double LF = 0.0; + double CF = 0.0; double GBetaF = 0.0; double DBetaF = 0.0; for (unsigned int e = 0; e < Dim; ++e){ - RSigmaF += tau_one(d,d) * sigma(d,e) * rData.N[i] * (body_force[e] - MomentumProj[e] + OldUssTerm[e]); - DBetaF += 2.0 / 3.0 * tau_one(d,d) * kin_viscosity * rData.DN_DX(i,d) * fluid_fraction_gradient[e] * (body_force[e] - MomentumProj[e] + OldUssTerm[e]); - GBetaF += (tau_one(d,d) * kin_viscosity * (fluid_fraction_gradient[d] * rData.DN_DX(i,e)) * (body_force[e] - MomentumProj[e] + OldUssTerm[e])); - // GBetaF += tau_one(d,d) * kin_viscosity * (fluid_fraction_gradient[d] * rData.DN_DX(i,d)) * (body_force[e] - MomentumProj[e] + OldUssTerm[e]); - for (unsigned int f = 0; f < Dim; ++f){ - GBetaF += tau_one(d,d) * kin_viscosity * (fluid_fraction_gradient[f] * rData.DN_DX(i,f)) * (body_force[e] - MomentumProj[e] + OldUssTerm[e]); - } + LF += tau_one(d,d) * fluid_fraction * viscosity * rData.DDN_DDX[i](d,e) * (body_force[e] - MomentumProj[e] + OldUssTerm[e]); + LF += tau_one(d,d) * fluid_fraction * viscosity * rData.DDN_DDX[i](e,e) * (body_force[d] - MomentumProj[d] + OldUssTerm[d]); + CF += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * rData.DDN_DDX[i](d,e) * (body_force[e] - MomentumProj[e] + OldUssTerm[e]); + GBetaF += tau_one(d,d) * viscosity * fluid_fraction_gradient[d] * rData.DN_DX(i,e) * (body_force[e] - MomentumProj[e] + OldUssTerm[e]); + GBetaF += tau_one(d,d) * viscosity * fluid_fraction_gradient[e] * rData.DN_DX(i,e) * (body_force[d] - MomentumProj[d] + OldUssTerm[d]); + DBetaF += 2.0 / 3.0 * tau_one(d,d) * viscosity * rData.DN_DX(i,d) * fluid_fraction_gradient[e] * (body_force[e] - MomentumProj[e] + OldUssTerm[e]); } // Grad(q) * TauOne * (Density * BodyForce - Projection) QAlphaF += tau_one(d,d) * rData.DN_DX(i,d) * fluid_fraction * (body_force[d] - MomentumProj[d] + OldUssTerm[d]); - double VPhi = tau_two * rData.N[i] * fluid_fraction_gradient[d] * (mass_source - fluid_fraction_rate - MassProj); + VPhi += tau_two * rData.N[i] * fluid_fraction_gradient[d] * (mass_source - fluid_fraction_rate - MassProj); + // OSS pressure subscale projection double DPhi = rData.DN_DX(i,d) * tau_two * fluid_fraction * (mass_source - fluid_fraction_rate - MassProj); - rLocalRHS[row+d] += rData.Weight * (VF - VI + AF + DPhi - RSigmaF + GBetaF - DBetaF + VPhi); + + rLocalRHS[row+d] += rData.Weight * (VF - VI + AF + LF - CF + DPhi + GBetaF - DBetaF + VPhi); } double Q = rData.N[i] * (mass_source - fluid_fraction_rate); + rLocalRHS[row+Dim] += rData.Weight * (QAlphaF + Q); // Grad(q) * TauOne * (Density * BodyForce) } + // Adding reactive terms to the stabilization + if(!rData.UseOSS) + this->AddReactionStabilization(rData,LHS,rLocalRHS); + // Write (the linearized part of the) local contribution into residual form (A*dx = b - A*x) array_1d values; this->GetCurrentValuesVector(rData,values); noalias(rLocalRHS) -= prod(LHS, values); - /* Viscous contribution (with symmetric gradient 2*nu*{E(u) - 1/3 Tr(E)} ) - * For a generic (potentially non-linear) constitutive law, one cannot assume that RHS = F - LHS*current_values. - * Because of this, the AddViscousTerm function manages both the LHS and the RHS. - */ - this->AddViscousTerm(rData,LHS,rLocalRHS); - noalias(rLocalLHS) += LHS; } +template +void AlternativeDVMSDEMCoupled::CalculateMassMatrix(MatrixType& rMassMatrix, + const ProcessInfo& rCurrentProcessInfo) +{ + // Resize and intialize output + if (rMassMatrix.size1() != LocalSize) + rMassMatrix.resize(LocalSize, LocalSize, false); + + noalias(rMassMatrix) = ZeroMatrix(LocalSize, LocalSize); + + if (!TElementData::ElementManagesTimeIntegration) { + // Get Shape function data + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + DenseVector> shape_function_second_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); + const unsigned int number_of_gauss_points = gauss_weights.size(); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + // Iterate over integration points to evaluate local contribution + for (unsigned int g = 0; g < number_of_gauss_points; g++) { + this->UpdateIntegrationPointDataSecondDerivatives( + data, g, gauss_weights[g], + row(shape_functions, g),shape_derivatives[g],shape_function_second_derivatives[g]); + + this->AddMassLHS(data, rMassMatrix); + } + } +} + +template +void AlternativeDVMSDEMCoupled::CalculateLocalVelocityContribution(MatrixType& rDampMatrix, + VectorType& rRightHandSideVector, + const ProcessInfo& rCurrentProcessInfo) +{ + // Resize and intialize output + if( rDampMatrix.size1() != LocalSize ) + rDampMatrix.resize(LocalSize,LocalSize,false); + + if( rRightHandSideVector.size() != LocalSize ) + rRightHandSideVector.resize(LocalSize,false); + + noalias(rDampMatrix) = ZeroMatrix(LocalSize,LocalSize); + noalias(rRightHandSideVector) = ZeroVector(LocalSize); + + if (!TElementData::ElementManagesTimeIntegration) { + // Get Shape function data + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + DenseVector> shape_function_second_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + const unsigned int number_of_gauss_points = gauss_weights.size(); + + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + // Iterate over integration points to evaluate local contribution + for (unsigned int g = 0; g < number_of_gauss_points; g++) { + const auto& r_dndx = shape_derivatives[g]; + this->UpdateIntegrationPointDataSecondDerivatives( + data, g, gauss_weights[g], + row(shape_functions, g),r_dndx, shape_function_second_derivatives[g]); + + this->AddVelocitySystem(data, rDampMatrix, rRightHandSideVector); + } + } +} + +template < class TElementData > +void AlternativeDVMSDEMCoupled::CalculateResistanceTensor( + const TElementData& rData) +{ + BoundedMatrix& rsigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; + BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); + + rsigma = permeability; +} + template< class TElementData > void AlternativeDVMSDEMCoupled::AddMassLHS( TElementData& rData, @@ -636,13 +968,115 @@ void AlternativeDVMSDEMCoupled::MassProjTerm( for (unsigned int i = 0; i < NumNodes; i++) { for (unsigned int d = 0; d < Dim; ++d) { - rMassRHS -= fluid_fraction * rData.DN_DX(i, d) * velocities(i, d) + fluid_fraction_gradient[d] * rData.N[i] * velocities(i,d); + rMassRHS -= fluid_fraction * rData.DN_DX(i,d) * velocities(i,d) + fluid_fraction_gradient[d] * rData.N[i] * velocities(i,d); } } rMassRHS += mass_source - fluid_fraction_rate; } -/////////////////////////////////////////////////////////////////////////////////////////////////// + +template +void AlternativeDVMSDEMCoupled::AddReactionStabilization( + TElementData& rData, + BoundedMatrix& rLHS, + VectorType& rLocalRHS) +{ + + const double density = this->GetAtCoordinate(rData.Density, rData.N); + + BoundedMatrix tau_one = ZeroMatrix(Dim, Dim); + double tau_two; + const array_1d convective_velocity = this->FullConvectiveVelocity(rData); + + this->CalculateStabilizationParameters(rData, convective_velocity, tau_one, tau_two); + + array_1d body_force = density * this->GetAtCoordinate(rData.BodyForce, rData.N); + + Vector AGradN; + this->ConvectionOperator(AGradN, convective_velocity, rData.DN_DX); // Get a * grad(Ni) + + AGradN *= density; + + const double dt = rData.DeltaTime; + + // small scale velocity contributions (subscale tracking) + array_1d OldUssTerm = (density/dt) * mOldSubscaleVelocity[rData.IntegrationPointIndex]; // rho * u_ss^{n-1}/dt + + const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); + const double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); + + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; + + // Note: Dof order is (vx,vy,[vz,]p) for each node + for (unsigned int i = 0; i < NumNodes; i++) + { + unsigned int row = i*BlockSize; + // Loop over columns + for (unsigned int j = 0; j < NumNodes; j++) + { + unsigned int col = j*BlockSize; + + for (unsigned int d = 0; d < Dim; d++) // iterate over dimensions for velocity Dofs in this node combination + { + double RSigmaG = 0.0; + double GR = 0.0; + for (unsigned int e = 0; e < Dim; e++){ + double ASigma = tau_one(d,d) * fluid_fraction * AGradN[i] * rData.N[j] * sigma(d,e); + double RSigmaA = tau_one(d,d) * fluid_fraction * rData.N[i] * AGradN[j] * sigma(d,e); + double VSigma = tau_one(d,d) * fluid_fraction * density/dt * rData.N[i] * rData.N[j] * sigma(d,e); + double LSigma_1 = 0.0; + double LSigma_2 = 0.0; + double CSigma = 0.0; + double GBetaSigma_1 = 0.0; + double GBetaSigma_2 = 0.0; + double DBetaSigma = 0.0; + double RSigmaL_1 = 0.0; + double RSigmaL_2 = 0.0; + double RSigmaC = 0.0; + double RGBeta_1 = 0.0; + double RGBeta_2 = 0.0; + double RDBeta = 0.0; + double RRSigma = 0.0; + GR += tau_one(d,d) * fluid_fraction * rData.DN_DX(i,e) * sigma(e,d) * rData.N[j]; + for (unsigned int f = 0; f < Dim; f++){ + LSigma_1 += tau_one(d,d) * fluid_fraction * viscosity * rData.DDN_DDX[i](f,f) * sigma(d,e) * rData.N[j]; + LSigma_2 += tau_one(d,d) * fluid_fraction * viscosity * rData.DDN_DDX[i](d,f) * sigma(f,e) * rData.N[j]; + CSigma += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * rData.DDN_DDX[i](f,d) * sigma(f,e) * rData.N[j]; + GBetaSigma_1 += tau_one(d,d) * viscosity * fluid_fraction_gradient[d] * rData.DN_DX(i,f) * sigma(f,e) * rData.N[j]; + GBetaSigma_2 += tau_one(d,d) * viscosity * fluid_fraction_gradient[f] * rData.DN_DX(i,f) * sigma(d,e) * rData.N[j]; + RSigmaL_1 += tau_one(d,d) * fluid_fraction * viscosity * rData.N[i] * sigma(d,e) * rData.DDN_DDX[j](f,f); + RSigmaL_2 += tau_one(d,d) * fluid_fraction * viscosity * rData.N[i] * sigma(d,f) * rData.DDN_DDX[j](e,f); + RSigmaC += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * sigma(d,f) * rData.N[i] * rData.DDN_DDX[j](f,e); + RGBeta_1 += tau_one(d,d) * viscosity * rData.N[i] * fluid_fraction_gradient[e] * sigma(d,f) * rData.DN_DX(j,f); + RGBeta_2 += tau_one(d,d) * viscosity * rData.N[i] * fluid_fraction_gradient[f] * rData.DN_DX(j,f) * sigma(d,e); + RDBeta += 2.0/3.0 * tau_one(d,d) * viscosity * rData.N[i] * sigma(d,f) * fluid_fraction_gradient[f] * rData.DN_DX(j,e); + RRSigma += tau_one(d,d) * sigma(d,f) * rData.N[i] * sigma(f,e) * rData.N[j]; + DBetaSigma += 2.0 / 3.0 * tau_one(d,d) * viscosity * rData.DN_DX(i,d) * rData.N[j] * fluid_fraction_gradient[f] * sigma(f,e); + } + double LSigma = LSigma_1 + LSigma_2; + double GBetaSigma = GBetaSigma_1 + GBetaSigma_2; + double RSigmaL = RSigmaL_1 + RSigmaL_2; + double RGBeta = RGBeta_1 + RGBeta_2; + RSigmaG += tau_one(d,d) * fluid_fraction * sigma(d,e) * rData.N[i] * rData.DN_DX(j,e); + rLHS(row+d,col+e) += rData.Weight * (GBetaSigma + RGBeta - DBetaSigma - RDBeta + ASigma - RRSigma - RSigmaA + LSigma - CSigma + RSigmaL - RSigmaC - VSigma); + } + rLHS(row+Dim,col+d) += rData.Weight * (GR); + rLHS(row+d,col+Dim) += rData.Weight * (-RSigmaG); + } + } + + // RHS terms + for (unsigned int d = 0; d < Dim; ++d) + { + double RSigmaF = 0.0; + for (unsigned int e = 0; e < Dim; ++e){ + RSigmaF += tau_one(d,d) * rData.N[i] * sigma(d,e) * (body_force[e] + OldUssTerm[e]); /*- momentum_projection[e]*/ //momentum_projection 0 because is ASGS + } + rLocalRHS[row+d] += rData.Weight * (- RSigmaF); + } + } +} template< class TElementData > void AlternativeDVMSDEMCoupled::AddMassStabilization( @@ -665,23 +1099,18 @@ void AlternativeDVMSDEMCoupled::AddMassStabilization( AGradN *= density; const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); - array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); - double kin_viscosity = viscosity / density; - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); + const double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); + BoundedMatrix sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); double W = rData.Weight * density; // This density is for the dynamic term in the residual (rho*Du/Dt) - sigma *= viscosity; // Note: Dof order is (u,v,[w,]p) for each node - for (unsigned int i = 0; i < NumNodes; i++) { + for (unsigned int i = 0; i < NumNodes; i++){ unsigned int row = i*BlockSize; - for (unsigned int j = 0; j < NumNodes; j++) { + for (unsigned int j = 0; j < NumNodes; j++){ unsigned int col = j*BlockSize; for (unsigned int d = 0; d < Dim; d++) @@ -691,16 +1120,23 @@ void AlternativeDVMSDEMCoupled::AddMassStabilization( // u*grad(v) * TauOne * du/dt // v * TauOne/dt * du/dt (from v*d(uss)/dt) double AU = tau_one(d,d) * fluid_fraction * fluid_fraction * AGradN[i] * rData.N[j]; - double IU = tau_one(d,d) * std::pow(fluid_fraction, 2) * rData.N[i]/dt * rData.N[j]; - double GBetaUDiag = tau_one(d,d) * fluid_fraction * kin_viscosity * (fluid_fraction_gradient[d] * rData.DN_DX(i,d)) * rData.N[j]; + double IU = tau_one(d,d) * std::pow(fluid_fraction,2) * density * rData.N[i]/dt * rData.N[j]; for (unsigned int e = 0; e < Dim; ++e){ - double RSigmaU = tau_one(d,d) * sigma(d,e) * rData.N[i] * rData.N[j]; - double DBetaU = 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * kin_viscosity * rData.DN_DX(i,d) * rData.N[j] * fluid_fraction_gradient[e]; - double GBetaU = tau_one(d,d) * fluid_fraction * kin_viscosity * (fluid_fraction_gradient[d] * rData.DN_DX(i,e)) * rData.N[j]; + double LI = tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[i](d,e) * rData.N[j]; + double CI = 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[i](d,e) * rData.N[j]; + double RSigmaU = tau_one(d,d) * fluid_fraction * sigma(d,e) * rData.N[i] * rData.N[j]; + double DBetaU = 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * rData.DN_DX(i,d) * rData.N[j] * fluid_fraction_gradient[e]; + double GBetaU = tau_one(d,d) * fluid_fraction * viscosity * fluid_fraction_gradient[d] * rData.DN_DX(i,e) * rData.N[j]; + for (unsigned int f = 0; f < Dim; ++f){ + if (d == e){ + LI += tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[i](f,f) * rData.N[j]; + GBetaU += tau_one(d,d) * fluid_fraction * viscosity * fluid_fraction_gradient[f] * rData.DN_DX(i,f) * rData.N[j]; + } + } - rMassMatrix(row+d, col+e) += W * (GBetaU - RSigmaU - DBetaU); + rMassMatrix(row+d, col+e) += W * (GBetaU + LI - CI - RSigmaU - DBetaU); } - rMassMatrix(row+d,col+d) += W * (AU - IU + GBetaUDiag); + rMassMatrix(row+d,col+d) += W * (AU - IU); rMassMatrix(row+Dim,col+d) += W * UGAlpha; } } @@ -716,9 +1152,11 @@ void AlternativeDVMSDEMCoupled::CalculateProjections(const Process Vector gauss_weights; Matrix shape_functions; ShapeFunctionDerivativesArrayType shape_function_derivatives; + DenseVector> shape_function_second_derivatives; this->CalculateGeometryData(gauss_weights,shape_functions,shape_function_derivatives); const unsigned int NumGauss = gauss_weights.size(); - + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); VectorType MomentumRHS = ZeroVector(NumNodes * Dim); VectorType MassRHS = ZeroVector(NumNodes); VectorType NodalArea = ZeroVector(NumNodes); @@ -728,9 +1166,8 @@ void AlternativeDVMSDEMCoupled::CalculateProjections(const Process for (unsigned int g = 0; g < NumGauss; g++) { - this->UpdateIntegrationPointData( - data, g, gauss_weights[g], - row(shape_functions,g),shape_function_derivatives[g]); + this->UpdateIntegrationPointDataSecondDerivatives( + data, g, gauss_weights[g], row(shape_functions,g),shape_function_derivatives[g],shape_function_second_derivatives[g]); array_1d MomentumRes = ZeroVector(3); double MassRes = 0.0; @@ -798,38 +1235,37 @@ void AlternativeDVMSDEMCoupled::CalculateStabilizationParameters( const double h = rData.ElementSize; const double density = this->GetAtCoordinate(rData.Density,rData.N); const double viscosity = this->GetAtCoordinate(rData.EffectiveViscosity,rData.N); - double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); - constexpr double c1 = DVMS::mTauC1; - constexpr double c2 = DVMS::mTauC2; - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); + const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); + constexpr double c1 = 8.0; + constexpr double c2 = 2.0; + const int p = mInterpolationOrder; + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; BoundedMatrix I = IdentityMatrix(Dim, Dim); - array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); + // This last term does not exist physically and it is included to do the spectral radius taking into account the inverse Gamma + // whose size is (d+1,d+1) double velocity_modulus = 0.0; double fluid_fraction_gradient_modulus = 0.0; - double sigma_term = 0.0; for (unsigned int d = 0; d < Dim; d++){ velocity_modulus += Velocity[d] * Velocity[d]; fluid_fraction_gradient_modulus += std::pow(fluid_fraction_gradient[d],2); - for (unsigned int e = d; e < Dim; e++){ - sigma_term += std::pow(sigma(d,e),2); - } } double velocity_norm = std::sqrt(velocity_modulus); double fluid_fraction_gradient_norm = std::sqrt(fluid_fraction_gradient_modulus); + double c_alpha = fluid_fraction + h / c1 * fluid_fraction_gradient_norm; - inv_tau = (c1 * viscosity / (h*h) + density * (c2 * velocity_norm / h ) ) * c_alpha + density * fluid_fraction / rData.DeltaTime + std::sqrt(sigma_term); - inv_tau_NS = c1 * viscosity / (h*h) + density * (c2 * velocity_norm / h ) + std::sqrt(sigma_term); - double tau_one = 1 / inv_tau; - double tau_one_NS = 1 / inv_tau_NS; + + inv_tau_NS = c1 * viscosity / std::pow(h/(p*p),2.0) + density * (c2 * velocity_norm / (h/p) ); + double tau_one_NS = 1.0 / inv_tau_NS; + + inv_tau = (c1 * viscosity / std::pow(h/(p*p),2.0) + density * (c2 * velocity_norm / (h/p) ) ) * c_alpha + density * fluid_fraction / rData.DeltaTime; + double tau_one = 1.0 / (inv_tau + sigma(0,0)); TauOne = tau_one * I; - TauTwo = h * h / (c1 * fluid_fraction * tau_one_NS); + TauTwo = std::pow(h/p,2.0) / (c1 * fluid_fraction * tau_one_NS); } template< class TElementData > @@ -904,27 +1340,23 @@ void AlternativeDVMSDEMCoupled::UpdateSubscaleVelocity( { const double density = this->GetAtCoordinate(rData.Density,rData.N); double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction,rData.N); - - array_1d predicted_subscale_velocity = ZeroVector(3); + array_1d predicted_subscale_velocity = ZeroVector(Dim); const array_1d& r_old_subscale_velocity = mOldSubscaleVelocity[rData.IntegrationPointIndex]; - array_1d previous_subscale_velocity = ZeroVector(3); - - array_1d previous_velocity = mPreviousVelocity[rData.IntegrationPointIndex]; + array_1d previous_velocity = mPreviousVelocity[rData.IntegrationPointIndex]; - for (size_t i = 0; i < NumNodes; i++) { - array_1d subscale_velocity_on_previous_iteration = mPredictedSubscaleVelocity[rData.IntegrationPointIndex]; - for (size_t d = 0; d < Dim; d++) { - previous_subscale_velocity[d] += subscale_velocity_on_previous_iteration[d]; - } - } + //for (size_t i = 0; i < NumNodes; i++) { + array_1d subscale_velocity_on_previous_iteration = mPredictedSubscaleVelocity[rData.IntegrationPointIndex]; + // for (size_t d = 0; d < Dim; d++) { + // previous_subscale_velocity[d] += subscale_velocity_on_previous_iteration[d]; + // } + //} - array_1d v_d = ZeroVector(Dim); + array_1d v_d = ZeroVector(3); for (unsigned int d = 0; d < Dim; d++) - { - v_d[d] = previous_velocity[d] + previous_subscale_velocity[d]; - } + v_d[d] = previous_velocity[d] + subscale_velocity_on_previous_iteration[d]; + const double dt = rData.DeltaTime; // Part of the residual that does not depend on the subscale @@ -935,16 +1367,14 @@ void AlternativeDVMSDEMCoupled::UpdateSubscaleVelocity( else this->OrthogonalMomentumResidual(rData,v_d,static_residual); - BoundedMatrix tau_one = ZeroMatrix(Dim, Dim); double tau_two; this->CalculateStabilizationParameters(rData,v_d,tau_one,tau_two); for (unsigned int d = 0; d < Dim; d++) - { predicted_subscale_velocity[d] = tau_one(d,d) * (static_residual[d] + fluid_fraction * (density/dt)*r_old_subscale_velocity[d]); - } + noalias(mPredictedSubscaleVelocity[rData.IntegrationPointIndex]) = predicted_subscale_velocity; } @@ -963,11 +1393,9 @@ void AlternativeDVMSDEMCoupled::UpdateSubscaleVelocityPrediction( // Elemental large-scale velocity gradient BoundedMatrix resolved_velocity_gradient = ZeroMatrix(Dim,Dim); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); - array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); + BoundedMatrix sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; + + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); const auto& r_resolved_velocities = rData.Velocity; @@ -1022,7 +1450,6 @@ void AlternativeDVMSDEMCoupled::UpdateSubscaleVelocityPrediction( while ( (!converged) && (iter++ < subscale_prediction_maximum_iterations) ) { - // Calculate new Tau double convection_velocity_norm_squared = 0.0; Vector v_d = ZeroVector(Dim); @@ -1119,6 +1546,9 @@ template class AlternativeDVMSDEMCoupled< QSVMSDEMCoupledData<2,3> >; template class AlternativeDVMSDEMCoupled< QSVMSDEMCoupledData<3,4> >; template class AlternativeDVMSDEMCoupled< QSVMSDEMCoupledData<2,4> >; +template class AlternativeDVMSDEMCoupled< QSVMSDEMCoupledData<2,6> >; +template class AlternativeDVMSDEMCoupled< QSVMSDEMCoupledData<2,9> >; template class AlternativeDVMSDEMCoupled< QSVMSDEMCoupledData<3,8> >; +template class AlternativeDVMSDEMCoupled< QSVMSDEMCoupledData<3,27> >; -} // namespace Kratos +} // namespace Kratos \ No newline at end of file diff --git a/applications/FluidDynamicsApplication/custom_elements/alternative_d_vms_dem_coupled.h b/applications/FluidDynamicsApplication/custom_elements/alternative_d_vms_dem_coupled.h index d19043e562d9..862312fe20a5 100644 --- a/applications/FluidDynamicsApplication/custom_elements/alternative_d_vms_dem_coupled.h +++ b/applications/FluidDynamicsApplication/custom_elements/alternative_d_vms_dem_coupled.h @@ -92,6 +92,8 @@ class AlternativeDVMSDEMCoupled : public DVMS /// Type for an array of shape function gradient matrices typedef GeometryType::ShapeFunctionsGradientsType ShapeFunctionDerivativesArrayType; + typedef GeometryType::ShapeFunctionsSecondDerivativesType ShapeFunctionsSecondDerivativesType; + constexpr static unsigned int Dim = DVMS::Dim; constexpr static unsigned int NumNodes = DVMS::NumNodes; constexpr static unsigned int BlockSize = DVMS::BlockSize; @@ -215,6 +217,8 @@ class AlternativeDVMSDEMCoupled : public DVMS DenseVector< array_1d > mPredictedSubscaleVelocity; DenseVector< array_1d > mOldSubscaleVelocity; DenseVector< array_1d > mPreviousVelocity; + DenseVector > mViscousResistanceTensor; + int mInterpolationOrder = 1; ///@} ///@name Protected Operators @@ -242,16 +246,33 @@ class AlternativeDVMSDEMCoupled : public DVMS MatrixType& rLocalLHS, VectorType& rLocalRHS) override; + void CalculateMassMatrix(MatrixType& rMassMatrix, + const ProcessInfo& rCurrentProcessInfo) override; + + void CalculateLocalVelocityContribution( + MatrixType& rDampMatrix, + VectorType& rRightHandSideVector, + const ProcessInfo& rCurrentProcessInfo) override; + // Implementation details of AlternativeDVMSDEMCoupled ///////////////////////////////////////// void AddMassLHS( TElementData& rData, MatrixType& rMassMatrix) override; + void CalculateResistanceTensor( + const TElementData& rData); + void AddMassStabilization( TElementData& rData, MatrixType& rMassMatrix) override; + void AddReactionStabilization( + TElementData& rData, + BoundedMatrix& rLHS, + VectorType& rLocalRHS); + + void AddViscousTerm( const TElementData& rData, BoundedMatrix& rLHS, @@ -259,6 +280,14 @@ class AlternativeDVMSDEMCoupled : public DVMS void CalculateProjections(const ProcessInfo &rCurrentProcessInfo) override; + void UpdateIntegrationPointDataSecondDerivatives( + TElementData& rData, + unsigned int IntegrationPointIndex, + double Weight, + const typename TElementData::MatrixRowType& rN, + const typename TElementData::ShapeDerivativesType& rDN_DX, + const typename TElementData::ShapeFunctionsSecondDerivativesType& rDDN_DDX) const; + void CalculateStabilizationParameters( const TElementData& rData, const array_1d &Velocity, @@ -290,6 +319,23 @@ class AlternativeDVMSDEMCoupled : public DVMS const Variable>& rVariable, array_1d& rOutput, const ProcessInfo& rCurrentProcessInfo) override; + void CalculateOnIntegrationPoints( + const Variable>& rVariable, + std::vector>& rOutput, + const ProcessInfo& rCurrentProcessInfo) override; + + void CalculateOnIntegrationPoints( + const Variable& rVariable, + std::vector& rOutput, + const ProcessInfo& rCurrentProcessInfo) override; + + void CalculateOnIntegrationPoints( + Variable const& rVariable, + std::vector& rValues, + ProcessInfo const& rCurrentProcessInfo) override; + + GeometryData::IntegrationMethod GetIntegrationMethod() const override; + ///@} ///@name Protected Access ///@{ diff --git a/applications/FluidDynamicsApplication/custom_elements/alternative_qs_vms_dem_coupled.cpp b/applications/FluidDynamicsApplication/custom_elements/alternative_qs_vms_dem_coupled.cpp index 08bc5fcc3d87..48bbf8b2c40b 100644 --- a/applications/FluidDynamicsApplication/custom_elements/alternative_qs_vms_dem_coupled.cpp +++ b/applications/FluidDynamicsApplication/custom_elements/alternative_qs_vms_dem_coupled.cpp @@ -20,10 +20,10 @@ #include "custom_utilities/qsvms_dem_coupled_data.h" #include "custom_utilities/fluid_element_utilities.h" #include "fluid_dynamics_application_variables.h" +#include "utilities/sparse_matrix_multiplication_utility.h" namespace Kratos { - //////////////////////////Life cycle template< class TElementData > @@ -66,6 +66,160 @@ Element::Pointer AlternativeQSVMSDEMCoupled::Create(IndexType NewI return Kratos::make_intrusive(NewId, pGeom, pProperties); } +template +void AlternativeQSVMSDEMCoupled::Initialize(const ProcessInfo& rCurrentProcessInfo) +{ + // Base class does things with constitutive law here. + QSVMS::Initialize(rCurrentProcessInfo); + + if(Dim == 2){ + if (NumNodes == 9 || NumNodes == 6 || NumNodes == 4) + mInterpolationOrder = 2; + } + else if(Dim == 3){ + if (NumNodes == 10 || NumNodes == 27) + mInterpolationOrder = 2; + } + + const unsigned int number_of_gauss_points = this->GetGeometry().IntegrationPointsNumber(this->GetIntegrationMethod()); + + // The old velocity may be already defined (if restarting) + // and we want to keep the loaded values in that case. + if (mPreviousVelocity.size() != number_of_gauss_points) + { + mPreviousVelocity.resize(number_of_gauss_points); + for (IndexType g = 0; g < number_of_gauss_points; g++) + mPreviousVelocity[g] = ZeroVector(Dim); + } + + if (mPredictedSubscaleVelocity.size() != number_of_gauss_points) + { + mPredictedSubscaleVelocity.resize(number_of_gauss_points); + for (IndexType g = 0; g < number_of_gauss_points; g++) + mPredictedSubscaleVelocity[g] = ZeroVector(Dim); + } + // The prediction is updated before each non-linear iteration: + // It is not stored in a restart and can be safely initialized. + + // The old velocity may be already defined (if restarting) + // and we want to keep the loaded values in that case. + if (mViscousResistanceTensor.size() != number_of_gauss_points) + { + mViscousResistanceTensor.resize(number_of_gauss_points, false); + for (IndexType g = 0; g < number_of_gauss_points; g++) + noalias(mViscousResistanceTensor[g]) = ZeroMatrix(Dim,Dim); + } +} + +template< class TElementData > +void AlternativeQSVMSDEMCoupled::CalculateOnIntegrationPoints( + const Variable& rVariable, + std::vector& rOutput, + const ProcessInfo& rCurrentProcessInfo) +{ + const GeometryType::IntegrationPointsArrayType integration_points = this->GetGeometry().IntegrationPoints(this->GetIntegrationMethod()); + const SizeType number_of_integration_points = integration_points.size(); + + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + + if (rOutput.size() != number_of_integration_points) + rOutput.resize(number_of_integration_points); + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + for (IndexType g = 0; g < number_of_integration_points; g++ ) { + data.UpdateGeometryValues(g, gauss_weights[g], row(shape_functions, g),shape_derivatives[g]); + if (rVariable == PRESSURE) { + const auto& r_pressure = data.Pressure; + double value = this->GetAtCoordinate(r_pressure,data.N); + rOutput[g] = value; + } + } +} + +template< class TElementData > +void AlternativeQSVMSDEMCoupled::CalculateOnIntegrationPoints( + const Variable& rVariable, + std::vector& rValues, + const ProcessInfo& rCurrentProcessInfo) +{ + const GeometryType::IntegrationPointsArrayType integration_points = this->GetGeometry().IntegrationPoints(this->GetIntegrationMethod()); + const SizeType number_of_integration_points = integration_points.size(); + + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + + if (rValues.size() != number_of_integration_points) + rValues.resize(number_of_integration_points); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + for (IndexType g = 0; g < number_of_integration_points; g++ ) { + data.UpdateGeometryValues(g, gauss_weights[g], row(shape_functions, g),shape_derivatives[g]); + Matrix value = ZeroMatrix(Dim, Dim); + if (rVariable == VELOCITY_GRADIENT) { + const auto& r_velocity = data.Velocity; + for (IndexType i = 0; i < NumNodes; i++) { + for (IndexType d = 0; d < Dim; d++) { + for (IndexType e = 0; e < Dim; e++) + value(d,e) += data.DN_DX(i,d) * r_velocity(i,e); + } + } + } + rValues[g] = value; + } +} + +template< class TElementData > +void AlternativeQSVMSDEMCoupled::CalculateOnIntegrationPoints( + const Variable>& rVariable, + std::vector>& rOutput, + const ProcessInfo& rCurrentProcessInfo) +{ + const GeometryType::IntegrationPointsArrayType integration_points = this->GetGeometry().IntegrationPoints(this->GetIntegrationMethod()); + const SizeType number_of_integration_points = integration_points.size(); + + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + + if (rOutput.size() != number_of_integration_points) + rOutput.resize(number_of_integration_points); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + for (unsigned int g = 0; g < number_of_integration_points; g++ ) { + data.UpdateGeometryValues(g, gauss_weights[g], row(shape_functions, g),shape_derivatives[g]); + array_1d value(3,0.0); + if (rVariable == VELOCITY) { + const auto& r_velocity = data.Velocity; + value = this->GetAtCoordinate(r_velocity,data.N); + } + if (rVariable == BODY_FORCE) { + value = this->GetAtCoordinate(data.BodyForce,data.N); + } + if (rVariable == PRESSURE_GRADIENT){ + const auto& r_pressure = data.Pressure; + for (unsigned int i = 0; i < NumNodes; i++) { + for (unsigned int d = 0; d < Dim; d++) { + value[d] += r_pressure[i] * data.DN_DX(i,d); + } + } + } + rOutput[g] = value; + } +} + template void AlternativeQSVMSDEMCoupled::Calculate( const Variable>& rVariable, @@ -79,9 +233,11 @@ void AlternativeQSVMSDEMCoupled::Calculate( Vector GaussWeights; Matrix ShapeFunctions; ShapeFunctionDerivativesArrayType ShapeDerivatives; + DenseVector> shape_function_second_derivatives; this->CalculateGeometryData(GaussWeights,ShapeFunctions,ShapeDerivatives); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); const unsigned int NumGauss = GaussWeights.size(); - array_1d momentum_rhs = ZeroVector(NumNodes*Dim); VectorType MassRHS = ZeroVector(NumNodes); VectorType NodalArea = ZeroVector(NumNodes); @@ -90,53 +246,71 @@ void AlternativeQSVMSDEMCoupled::Calculate( data.Initialize(*this, rCurrentProcessInfo); for (unsigned int g = 0; g < NumGauss; g++) { - this->UpdateIntegrationPointData(data, g, GaussWeights[g], row(ShapeFunctions, g), ShapeDerivatives[g]); + + this->UpdateIntegrationPointDataSecondDerivatives(data, g, GaussWeights[g], row(ShapeFunctions, g), ShapeDerivatives[g], shape_function_second_derivatives[g]); array_1d MomentumRes = ZeroVector(3); double MassRes = 0.0; - array_1d convective_velocity = this->GetAtCoordinate(data.Velocity,data.N) - this->GetAtCoordinate(data.MeshVelocity,data.N); - + //array_1d convective_velocity = this->GetAtCoordinate(data.Velocity,data.N) - this->GetAtCoordinate(data.MeshVelocity,data.N); + array_1d convective_velocity = this->FullConvectiveVelocity(data); this->MomentumProjTerm(data, convective_velocity, MomentumRes); this->MassProjTerm(data,MassRes); - for (unsigned int i = 0; i < NumNodes; i++) + /* Projections of the elemental residual are computed with + * Newton-Raphson iterations of type M(lumped) dx = ElemRes - M(consistent) * x + */ + + // Carefully write results to nodal variables, to avoid parallelism problems + for (unsigned int i = 0; i < NumNodes; ++i) { double W = data.Weight*data.N[i]; + // Write nodal area unsigned int row = i*Dim; + //auto& momentum_rhs = this->GetGeometry()[i].GetValue(ADVPROJ); + //double& MassRHS = this->GetGeometry()[i].GetValue(DIVPROJ); for (unsigned int d = 0; d < Dim; d++) - momentum_rhs[row+d] += W*MomentumRes[d]; + momentum_rhs[row+d] += data.N[i]*MomentumRes[d]; NodalArea[i] += W; - MassRHS[i] += W*MassRes; + MassRHS[i] += data.N[i]*MassRes; } } - /* Projections of the elemental residual are computed with - * Newton-Raphson iterations of type M(lumped) dx = ElemRes - M(consistent) * x - */ - // Carefully write results to nodal variables, to avoid parallelism problems - for (unsigned int i = 0; i < NumNodes; ++i) + + for (SizeType i = 0; i < NumNodes; ++i) { - this->GetGeometry()[i].SetLock(); // So it is safe to write in the node in OpenMP + unsigned int row_i = i*Dim; double W = data.Weight*data.N[i]; - // Write nodal area - this->GetGeometry()[i].FastGetSolutionStepValue(NODAL_AREA) +=NodalArea[i]; - + this->GetGeometry()[i].SetLock(); // So it is safe to write in the node in OpenMP + auto& rMomValue = this->GetGeometry()[i].GetValue(ADVPROJ); + this->GetGeometry()[i].FastGetSolutionStepValue(NODAL_AREA) += NodalArea[i]; // Substract M(consistent)*x(i-1) from RHS for(unsigned int j = 0; j < NumNodes; ++j) // RHS -= Weigth * Ones(TNumNodes,TNumNodes) * x(i-1) { + unsigned int row_j = j*Dim; for(unsigned int d = 0; d < Dim; ++d) - momentum_rhs[d] -= W * this->GetGeometry()[j].FastGetSolutionStepValue(ADVPROJ)[d]; + momentum_rhs[row_j+d] -= W * this->GetGeometry()[j].FastGetSolutionStepValue(ADVPROJ)[d]; MassRHS[j] -= W * this->GetGeometry()[j].FastGetSolutionStepValue(DIVPROJ); } - for(unsigned int d = 0; d < Dim; ++d) // RHS -= Weigth * Identity(TNumNodes,TNumNodes) * x(i-1) - momentum_rhs[d] -= W * this->GetGeometry()[i].FastGetSolutionStepValue(ADVPROJ)[d]; + for(unsigned int d = 0; d < Dim; ++d){ // RHS -= Weigth * Identity(TNumNodes,TNumNodes) * x(i-1) + momentum_rhs[row_i+d] -= W * this->GetGeometry()[i].FastGetSolutionStepValue(ADVPROJ)[d]; + rMomValue[d] += momentum_rhs[row_i+d]; + } MassRHS[i] -= W * this->GetGeometry()[i].FastGetSolutionStepValue(DIVPROJ); + this->GetGeometry()[i].GetValue(DIVPROJ) += MassRHS[i]; this->GetGeometry()[i].UnSetLock(); // Free the node for other threads } - } } +template< class TElementData > +GeometryData::IntegrationMethod AlternativeQSVMSDEMCoupled::GetIntegrationMethod() const +{ + if(mInterpolationOrder == 1) + return GeometryData::IntegrationMethod::GI_GAUSS_2; + else + return GeometryData::IntegrationMethod::GI_GAUSS_3; +} + /////////////////////////////////////////////////////////////////////////////////////////////////// // Inquiry @@ -175,6 +349,64 @@ void AlternativeQSVMSDEMCoupled::PrintInfo(std::ostream& rOStream) rOStream << "AlternativeQSVMSDEMCoupled" << Dim << "D"; } +template +void AlternativeQSVMSDEMCoupled::InitializeNonLinearIteration(const ProcessInfo& rCurrentProcessInfo) +{ + // Get Shape function data + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_function_derivatives; + DenseVector> shape_function_second_derivatives; + this->CalculateGeometryData(gauss_weights,shape_functions,shape_function_derivatives); + const unsigned int number_of_integration_points = gauss_weights.size(); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); + TElementData data; + data.Initialize(*this,rCurrentProcessInfo); + + for (unsigned int g = 0; g < number_of_integration_points; g++) { + this->UpdateIntegrationPointDataSecondDerivatives(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g],shape_function_second_derivatives[g]); + + this->CalculateResistanceTensor(data); + //this->UpdateSubscaleVelocity(data); + } +} + +template +void AlternativeQSVMSDEMCoupled::FinalizeNonLinearIteration(const ProcessInfo& rCurrentProcessInfo) +{ + //Get Shape function data + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_function_derivatives; + DenseVector> shape_function_second_derivatives; + this->CalculateGeometryData(gauss_weights,shape_functions,shape_function_derivatives); + const unsigned int number_of_integration_points = gauss_weights.size(); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); + TElementData data; + data.Initialize(*this,rCurrentProcessInfo); + + for (unsigned int g = 0; g < number_of_integration_points; g++) { + this->UpdateIntegrationPointDataSecondDerivatives(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g],shape_function_second_derivatives[g]); + + this->UpdateSubscaleVelocity(data); + } +} + +template +void AlternativeQSVMSDEMCoupled::UpdateIntegrationPointDataSecondDerivatives( + TElementData& rData, + unsigned int IntegrationPointIndex, + double Weight, + const typename TElementData::MatrixRowType& rN, + const typename TElementData::ShapeDerivativesType& rDN_DX, + const typename TElementData::ShapeFunctionsSecondDerivativesType& rDDN_DDX) const +{ + this->UpdateIntegrationPointData(rData, IntegrationPointIndex, Weight, rN, rDN_DX); + rData.UpdateSecondDerivativesValues(rDDN_DDX); +} + template< class TElementData > void AlternativeQSVMSDEMCoupled::AlgebraicMomentumResidual( const TElementData& rData, @@ -189,35 +421,41 @@ void AlternativeQSVMSDEMCoupled::AlgebraicMomentumResidual( const double density = this->GetAtCoordinate(rData.Density,rData.N); const double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); - const auto& r_body_forces = rData.BodyForce; + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; + const auto& body_force = this->GetAtCoordinate(rData.BodyForce, rData.N); + const auto& r_velocities = rData.Velocity; const auto& r_pressures = rData.Pressure; const auto& fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); - sigma *= viscosity; - Vector grad_alpha_sym_grad_u, sigma_U; + Vector grad_alpha_sym_grad_u, sigma_U, grad_div_u, div_sym_grad_u; BoundedMatrix sym_gradient_u; for (unsigned int i = 0; i < NumNodes; i++) { - const array_1d& r_acceleration = rGeom[i].FastGetSolutionStepValue(ACCELERATION); - sigma_U = ZeroVector(Dim); - sym_gradient_u = ZeroMatrix(Dim, Dim); - grad_alpha_sym_grad_u = ZeroVector(Dim); - for (unsigned int d = 0; d < Dim; d++) { - double div_u = 0.0; - for (unsigned int e = 0; e < Dim; e++){ - sigma_U[d] += sigma(d,e) * rData.N[i] * r_velocities(i,e); - sym_gradient_u(d,e) += 1.0/2.0 * (rData.DN_DX(i,d) * r_velocities(i,e) + rData.DN_DX(i,e) * r_velocities(i,d)); - grad_alpha_sym_grad_u[d] += fluid_fraction_gradient[e] * sym_gradient_u(d,e); - div_u += rData.DN_DX(i,e) * r_velocities(i,e); - } - rResidual[d] += density * (rData.N[i] * r_body_forces(i,d) - fluid_fraction * rData.N[i] * r_acceleration[d] - fluid_fraction * convection[i] * r_velocities(i,d)) + 2 * grad_alpha_sym_grad_u[d] * viscosity - 2.0 / 3.0 * viscosity * fluid_fraction_gradient[d] * div_u - fluid_fraction * rData.DN_DX(i,d) * r_pressures[i] - sigma_U[d]; + const array_1d& r_acceleration = rGeom[i].FastGetSolutionStepValue(ACCELERATION); + sigma_U = ZeroVector(Dim); + grad_div_u = ZeroVector(Dim); + sym_gradient_u = ZeroMatrix(Dim, Dim); + grad_alpha_sym_grad_u = ZeroVector(Dim); + div_sym_grad_u = ZeroVector(Dim); + for (unsigned int d = 0; d < Dim; d++) { + double div_u = 0.0; + for (unsigned int e = 0; e < Dim; e++){ + sigma_U[d] += sigma(d,e) * rData.N[i] * r_velocities(i,e); + sym_gradient_u(d,e) += 1.0/2.0 * (rData.DN_DX(i,d) * r_velocities(i,e) + rData.DN_DX(i,e) * r_velocities(i,d)); + grad_alpha_sym_grad_u[d] += fluid_fraction_gradient[e] * sym_gradient_u(d,e); + div_u += rData.DN_DX(i,e) * r_velocities(i,e); + grad_div_u[d] += rData.DDN_DDX[i](d,e) * r_velocities(i,e); + if (d == e) + div_sym_grad_u[d] += rData.DDN_DDX[i](e,e) * r_velocities(i,d); + else + div_sym_grad_u[d] += 1.0/2.0 * (rData.DDN_DDX[i](e,d) * r_velocities(i,e) + rData.DDN_DDX[i](e,e) * r_velocities(i,d)); + } + rResidual[d] += density * (- fluid_fraction * rData.N[i] * r_acceleration[d] - fluid_fraction * convection[i] * r_velocities(i,d)) + 2.0 * grad_alpha_sym_grad_u[d] * viscosity - 2.0 / 3.0 * viscosity * fluid_fraction_gradient[d] * div_u + 2.0 * fluid_fraction * viscosity * div_sym_grad_u[d] - 2.0/3.0 * fluid_fraction * viscosity * grad_div_u[d] - fluid_fraction * rData.DN_DX(i,d) * r_pressures[i] - sigma_U[d]; } } + for (unsigned int d = 0; d < Dim; d++) + rResidual[d] += density * body_force[d]; } template< class TElementData > @@ -226,41 +464,44 @@ void AlternativeQSVMSDEMCoupled::MomentumProjTerm( const array_1d& rConvectionVelocity, array_1d &rMomentumRHS) const { + //const auto& rGeom = this->GetGeometry(); + Vector AGradN; this->ConvectionOperator(AGradN,rConvectionVelocity,rData.DN_DX); const double density = this->GetAtCoordinate(rData.Density,rData.N); const double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); + const auto body_force = this->GetAtCoordinate(rData.BodyForce, rData.N); - const auto& r_body_forces = rData.BodyForce; - const auto& r_velocities = rData.Velocity; - const auto& r_pressures = rData.Pressure; - const auto& r_fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); + const auto r_velocities = rData.Velocity; + const auto r_pressures = rData.Pressure; + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - sigma *= viscosity; - Vector sigma_U, grad_alpha_sym_grad_u; + Vector grad_alpha_sym_grad_u, grad_div_u, div_sym_grad_u; BoundedMatrix sym_gradient_u; for (unsigned int i = 0; i < NumNodes; i++) { - sigma_U = ZeroVector(Dim); + grad_div_u = ZeroVector(Dim); sym_gradient_u = ZeroMatrix(Dim, Dim); grad_alpha_sym_grad_u = ZeroVector(Dim); + div_sym_grad_u = ZeroVector(Dim); for (unsigned int d = 0; d < Dim; d++) { double div_u = 0.0; for (unsigned int e = 0; e < Dim; e++){ - sigma_U[d] += sigma(d,e) * rData.N[i] * r_velocities(i,e); sym_gradient_u(d,e) += 1.0/2.0 * (rData.DN_DX(i,d) * r_velocities(i,e) + rData.DN_DX(i,e) * r_velocities(i,d)); - grad_alpha_sym_grad_u[d] += r_fluid_fraction_gradient[e] * sym_gradient_u(d,e); + grad_alpha_sym_grad_u[d] += fluid_fraction_gradient[e] * sym_gradient_u(d,e); div_u += rData.DN_DX(i,e) * r_velocities(i,e); + grad_div_u[d] += rData.DDN_DDX[i](d,e) * r_velocities(i,e); + if (d == e) + div_sym_grad_u[d] += rData.DDN_DDX[i](e,e) * r_velocities(i,d); + else + div_sym_grad_u[d] += 1.0/2.0 * (rData.DDN_DDX[i](e,d) * r_velocities(i,e) + rData.DDN_DDX[i](e,e) * r_velocities(i,d)); } - rMomentumRHS[d] += density * (rData.N[i] * r_body_forces(i,d) /*- fluid_fraction * rData.N[i] * r_acceleration[d]*/ - fluid_fraction * AGradN[i] * rData.Velocity(i,d)) + 2 * grad_alpha_sym_grad_u[d] * viscosity - 2.0/3.0 * viscosity * r_fluid_fraction_gradient[d] * div_u - fluid_fraction * rData.DN_DX(i,d) * r_pressures[i] - sigma_U[d]; + rMomentumRHS[d] += density * (- fluid_fraction * AGradN[i] * r_velocities(i,d)) + 2.0 * grad_alpha_sym_grad_u[d] * viscosity - 2.0/3.0 * viscosity * fluid_fraction_gradient[d] * div_u + 2.0 * fluid_fraction * viscosity * div_sym_grad_u[d] - 2.0/3.0 * fluid_fraction * viscosity * grad_div_u[d] - fluid_fraction * rData.DN_DX(i,d) * r_pressures[i]; } } + for (unsigned int d = 0; d < Dim; d++) + rMomentumRHS[d] += density * body_force[d]; } template @@ -269,7 +510,8 @@ void AlternativeQSVMSDEMCoupled::AddMassStabilization( MatrixType& rMassMatrix) { const double density = this->GetAtCoordinate(rData.Density,rData.N); - const array_1d convective_velocity= + + const array_1d convective_velocity = this->GetAtCoordinate(rData.Velocity, rData.N) - this->GetAtCoordinate(rData.MeshVelocity, rData.N); @@ -284,17 +526,11 @@ void AlternativeQSVMSDEMCoupled::AddMassStabilization( AGradN *= density; const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); - array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); - double kin_viscosity = viscosity / density; - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); - - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); + const double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; double W = rData.Weight * density; // This density is for the dynamic term in the residual (rho*Du) - sigma *= viscosity; // Note: Dof order is (u,v,[w,]p) for each node for (unsigned int i = 0; i < NumNodes; i++) { @@ -309,21 +545,124 @@ void AlternativeQSVMSDEMCoupled::AddMassStabilization( double UGAlpha = tau_one(d,d) * fluid_fraction * fluid_fraction * rData.DN_DX(i,d) * rData.N[j]; // u*grad(v) * TauOne * du double AU = tau_one(d,d) * fluid_fraction * fluid_fraction * AGradN[i] * rData.N[j]; - double GBetaUDiag = tau_one(d,d) * fluid_fraction * kin_viscosity * (fluid_fraction_gradient[d] * rData.DN_DX(i,d)) * rData.N[j]; + for (unsigned int e = 0; e < Dim; ++e){ - double RSigmaU = tau_one(d,d) * sigma(d,e) * rData.N[i] * rData.N[j]; - double DBetaU = 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * kin_viscosity * rData.DN_DX(i,d) * rData.N[j] * fluid_fraction_gradient[e]; - double GBetaU = tau_one(d,d) * fluid_fraction * kin_viscosity * (fluid_fraction_gradient[d] * rData.DN_DX(i,e)) * rData.N[j]; + double LI = tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[i](d,e) * rData.N[j]; + double CI = 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[i](d,e) * rData.N[j]; + double RSigmaU = tau_one(d,d) * fluid_fraction * sigma(d,e) * rData.N[i] * rData.N[j]; + double DBetaU = 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * rData.DN_DX(i,d) * rData.N[j] * fluid_fraction_gradient[e]; + double GBetaU = tau_one(d,d) * fluid_fraction * viscosity * fluid_fraction_gradient[d] * rData.DN_DX(i,e) * rData.N[j]; + for (unsigned int f = 0; f < Dim; ++f){ + if (d == e){ + LI += tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[i](f,f) * rData.N[j]; + GBetaU += tau_one(d,d) * fluid_fraction * viscosity * fluid_fraction_gradient[f] * rData.DN_DX(i,f) * rData.N[j]; + } + } - rMassMatrix(row+d, col+e) += W * (GBetaU - RSigmaU - DBetaU); + rMassMatrix(row+d, col+e) += W * (GBetaU + LI - CI - RSigmaU - DBetaU); } - rMassMatrix(row+d,col+d) += W * (AU + GBetaUDiag); + rMassMatrix(row+d,col+d) += W * (AU); rMassMatrix(row+Dim,col+d) += W * UGAlpha; } } } } +template +void AlternativeQSVMSDEMCoupled::AddReactionStabilization( + TElementData& rData, + BoundedMatrix& rLHS, + VectorType& rLocalRHS) +{ + + const double density = this->GetAtCoordinate(rData.Density, rData.N); + BoundedMatrix tau_one = ZeroMatrix(Dim, Dim); + double tau_two; + const array_1d convective_velocity = this->FullConvectiveVelocity(rData); + this->CalculateTau(rData, convective_velocity, tau_one, tau_two); + array_1d body_force = density * this->GetAtCoordinate(rData.BodyForce, rData.N); + + Vector AGradN; + this->ConvectionOperator(AGradN, convective_velocity, rData.DN_DX); // Get a * grad(Ni) + + AGradN *= density; + + const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); + + const double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); + + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; + + // Note: Dof order is (vx,vy,[vz,]p) for each node + for (unsigned int i = 0; i < NumNodes; i++) + { + unsigned int row = i*BlockSize; + // Loop over columns + for (unsigned int j = 0; j < NumNodes; j++) + { + unsigned int col = j*BlockSize; + + for (unsigned int d = 0; d < Dim; d++) // iterate over dimensions for velocity Dofs in this node combination + { + double RSigmaG = 0.0; + double GR = 0.0; + for (unsigned int e = 0; e < Dim; e++){ + double ASigma = tau_one(d,d) * fluid_fraction * AGradN[i] * rData.N[j] * sigma(d,e); + double RSigmaA = tau_one(d,d) * fluid_fraction * rData.N[i] * AGradN[j] * sigma(d,e); + double LSigma_1 = 0.0; + double LSigma_2 = 0.0; + double CSigma = 0.0; + double GBetaSigma_1 = 0.0; + double GBetaSigma_2 = 0.0; + double DBetaSigma = 0.0; + double RSigmaL_1 = 0.0; + double RSigmaL_2 = 0.0; + double RSigmaC = 0.0; + double RGBeta_1 = 0.0; + double RGBeta_2 = 0.0; + double RDBeta = 0.0; + double RRSigma = 0.0; + GR += tau_one(d,d) * fluid_fraction * rData.DN_DX(i,e) * sigma(e,d) * rData.N[j]; + for (unsigned int f = 0; f < Dim; f++){ + LSigma_1 += tau_one(d,d) * fluid_fraction * viscosity * rData.DDN_DDX[i](f,f) * sigma(d,e) * rData.N[j]; + LSigma_2 += tau_one(d,d) * fluid_fraction * viscosity * rData.DDN_DDX[i](d,f) * sigma(f,e) * rData.N[j]; + CSigma += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * rData.DDN_DDX[i](f,d) * sigma(f,e) * rData.N[j]; + GBetaSigma_1 += tau_one(d,d) * viscosity * fluid_fraction_gradient[d] * rData.DN_DX(i,f) * sigma(f,e) * rData.N[j]; + GBetaSigma_2 += tau_one(d,d) * viscosity * fluid_fraction_gradient[f] * rData.DN_DX(i,f) * sigma(d,e) * rData.N[j]; + RSigmaL_1 += tau_one(d,d) * fluid_fraction * viscosity * rData.N[i] * sigma(d,e) * rData.DDN_DDX[j](f,f); + RSigmaL_2 += tau_one(d,d) * fluid_fraction * viscosity * rData.N[i] * sigma(d,f) * rData.DDN_DDX[j](e,f); + RSigmaC += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * sigma(d,f) * rData.N[i] * rData.DDN_DDX[j](f,e); + RGBeta_1 += tau_one(d,d) * viscosity * rData.N[i] * fluid_fraction_gradient[e] * sigma(d,f) * rData.DN_DX(j,f); + RGBeta_2 += tau_one(d,d) * viscosity * rData.N[i] * fluid_fraction_gradient[f] * rData.DN_DX(j,f) * sigma(d,e); + RDBeta += 2.0/3.0 * tau_one(d,d) * viscosity * rData.N[i] * sigma(d,f) * fluid_fraction_gradient[f] * rData.DN_DX(j,e); + RRSigma += tau_one(d,d) * sigma(d,f) * rData.N[i] * sigma(f,e) * rData.N[j]; + DBetaSigma += 2.0 / 3.0 * tau_one(d,d) * viscosity * rData.DN_DX(i,d) * rData.N[j] * fluid_fraction_gradient[f] * sigma(f,e); + } + double LSigma = LSigma_1 + LSigma_2; + double GBetaSigma = GBetaSigma_1 + GBetaSigma_2; + double RSigmaL = RSigmaL_1 + RSigmaL_2; + double RGBeta = RGBeta_1 + RGBeta_2; + RSigmaG += tau_one(d,d) * fluid_fraction * sigma(d,e) * rData.N[i] * rData.DN_DX(j,e); + rLHS(row+d,col+e) += rData.Weight * (GBetaSigma + RGBeta - DBetaSigma - RDBeta + ASigma - RRSigma - RSigmaA + LSigma - CSigma + RSigmaL - RSigmaC); + } + rLHS(row+Dim,col+d) += rData.Weight * (GR); + rLHS(row+d,col+Dim) += rData.Weight * (-RSigmaG); + } + } + + // RHS terms + for (unsigned int d = 0; d < Dim; ++d) + { + double RSigmaF = 0.0; + for (unsigned int e = 0; e < Dim; ++e){ + RSigmaF += tau_one(d,d) * rData.N[i] * sigma(d,e) * body_force[e]; /*- momentum_projection[e]*/ //momentum_projection 0 because is ASGS + } + rLocalRHS[row+d] += rData.Weight * (- RSigmaF); + } + } +} + template void AlternativeQSVMSDEMCoupled::AddViscousTerm( const TElementData& rData, @@ -351,15 +690,19 @@ void AlternativeQSVMSDEMCoupled::AddVelocitySystem( MatrixType& rLocalLHS, VectorType& rLocalRHS) { - auto& LHS = rData.LHS; + BoundedMatrix& LHS = rData.LHS; LHS.clear(); - + //const auto& rGeom = this->GetGeometry(); const double density = this->GetAtCoordinate(rData.Density,rData.N); array_1d body_force = density * this->GetAtCoordinate(rData.BodyForce,rData.N); // Force per unit of volume - const array_1d convective_velocity = - this->GetAtCoordinate(rData.Velocity, rData.N) - - this->GetAtCoordinate(rData.MeshVelocity, rData.N); + const array_1d convective_velocity = this->FullConvectiveVelocity(rData); + array_1d velocity = this->GetAtCoordinate(rData.Velocity,rData.N); + + array_1d& r_prev_velocity = mPreviousVelocity[rData.IntegrationPointIndex]; + + for (unsigned int n = 0; n < Dim; n++) + r_prev_velocity[n] = velocity[n]; BoundedMatrix tau_one = ZeroMatrix(Dim, Dim); double tau_two; @@ -369,26 +712,19 @@ void AlternativeQSVMSDEMCoupled::AddVelocitySystem( this->ConvectionOperator(AGradN,convective_velocity,rData.DN_DX); // These two should be zero unless we are using OSS - const array_1d MomentumProj = this->GetAtCoordinate(rData.MomentumProjection,rData.N); - const double MassProj = this->GetAtCoordinate(rData.MassProjection,rData.N); + array_1d MomentumProj = this->GetAtCoordinate(rData.MomentumProjection,rData.N); + double MassProj = this->GetAtCoordinate(rData.MassProjection,rData.N); double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); - double kin_viscosity = viscosity / density; const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); const double fluid_fraction_rate = this->GetAtCoordinate(rData.FluidFractionRate, rData.N); const double mass_source = this->GetAtCoordinate(rData.MassSource, rData.N); + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); - array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); - - sigma *= viscosity; AGradN *= density; // Convective term is always multiplied by density - // Multiplying convective operator by density to have correct units // Note: Dof order is (u,v,[w,]p) for each node for (unsigned int i = 0; i < NumNodes; i++) { @@ -410,10 +746,8 @@ void AlternativeQSVMSDEMCoupled::AddVelocitySystem( // Stabilization: u*grad(v) * TauOne * u*grad(u) // The last term comes from vh*d(u_ss) double AA = tau_one(d,d) * AGradN[i] * std::pow(fluid_fraction, 2) * AGradN[j]; - double AGBetaDiag = tau_one(d,d) * fluid_fraction * kin_viscosity * AGradN[i] * (rData.DN_DX(j,d) * fluid_fraction_gradient[d]); - double GBetaADiag = kin_viscosity * fluid_fraction * tau_one(d,d) * AGradN[j] * fluid_fraction_gradient[d] * rData.DN_DX(i,d); - LHS(row+d,col+d) += rData.Weight * (V + AA - AGBetaDiag + GBetaADiag); + LHS(row+d,col+d) += rData.Weight * (V + AA); // Galerkin pressure term: Div(v) * p double P = fluid_fraction * rData.DN_DX(i,d) * rData.N[j]; @@ -421,77 +755,162 @@ void AlternativeQSVMSDEMCoupled::AddVelocitySystem( double GP = fluid_fraction_gradient[d] * rData.N[j] * rData.N[i]; - double GD = fluid_fraction_gradient[d] * rData.N[j] * rData.N[i]; + double GAlphaD = fluid_fraction_gradient[d] * rData.N[j] * rData.N[i]; /* q-p stabilization block */ // Stabilization: Grad(q) * TauOne * Grad(p) - G += tau_one(d,d) * fluid_fraction * fluid_fraction * rData.DN_DX(i,d) * rData.DN_DX(j,d); + G += tau_one(d,d) * std::pow(fluid_fraction,2) * rData.DN_DX(i,d) * rData.DN_DX(j,d); /* v-u block */ // Stabilization: Div(v) * TauTwo * Div(u) - double GR = 0.0; - double RSigmaG = 0.0; - double GG = 0.0; + double GG_1 = 0.0; + double GG_2 = 0.0; double DG = 0.0; - double GGBeta = 0.0; - double GDBeta = 0.0; - double GA = tau_one(d,d) * fluid_fraction * fluid_fraction * rData.DN_DX(i,d) * AGradN[j]; + double GGBeta_1 = 0.0; + double GGBeta_2 = 0.0; + double GC = 0.0; + double CG = 0.0; + double GL = 0.0; + double LG = 0.0; // Stabilization: (a * Grad(v)) * TauOne * Grad(p) - double AG = fluid_fraction * fluid_fraction * tau_one(d,d) * AGradN[i] * rData.DN_DX(j,d); + double AG = tau_one(d,d) * std::pow(fluid_fraction,2) * AGradN[i] * rData.DN_DX(j,d); + double GA = tau_one(d,d) * std::pow(fluid_fraction,2) * rData.DN_DX(i,d) * AGradN[j]; + double GDBeta = 0.0; for (unsigned int e = 0; e < Dim; e++){ - double GBetaGDiag = tau_one(d,d) * std::pow(kin_viscosity, 2) * fluid_fraction_gradient[d] * rData.DN_DX(i,d) * (rData.DN_DX(j,e) * fluid_fraction_gradient[e]); - GGBeta += tau_one(d,d) * fluid_fraction * kin_viscosity * (rData.DN_DX(i,e) * rData.DN_DX(j,e) * fluid_fraction_gradient[d]); - GGBeta += tau_one(d,d) * fluid_fraction * kin_viscosity * (rData.DN_DX(i,d) * fluid_fraction_gradient[e] * rData.DN_DX(j,e)); - GDBeta += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * kin_viscosity * fluid_fraction_gradient[e] * rData.DN_DX(i,e) * rData.DN_DX(j,d); + double DnuD = 2.0/3.0 * fluid_fraction * viscosity * rData.DN_DX(i,d) * rData.DN_DX(j,e); + double GS = fluid_fraction * viscosity * rData.DN_DX(i,e) * rData.DN_DX(j,d); + GDBeta += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * fluid_fraction_gradient[e] * rData.DN_DX(i,e) * rData.DN_DX(j,d); + GL += tau_one(d,d) * viscosity * std::pow(fluid_fraction,2) * rData.DN_DX(i,e) * rData.DDN_DDX[j](d,e); + GL += tau_one(d,d) * viscosity * std::pow(fluid_fraction,2) * rData.DN_DX(i,d) * rData.DDN_DDX[j](e,e); + GGBeta_1 += tau_one(d,d) * fluid_fraction * viscosity * rData.DN_DX(i,e) * rData.DN_DX(j,e) * fluid_fraction_gradient[d]; + GGBeta_2 += tau_one(d,d) * fluid_fraction * viscosity * rData.DN_DX(i,d) * rData.DN_DX(j,e) * fluid_fraction_gradient[e]; + GG_1 += tau_one(d,d) * fluid_fraction * viscosity * fluid_fraction_gradient[d] * rData.DN_DX(i,e) * rData.DN_DX(j,e); + GG_2 += tau_one(d,d) * fluid_fraction * viscosity * fluid_fraction_gradient[e] * rData.DN_DX(i,e) * rData.DN_DX(j,d); + LG += tau_one(d,d) * viscosity * std::pow(fluid_fraction,2) * rData.DN_DX(j,e) * rData.DDN_DDX[i](d,e); + LG += tau_one(d,d) * viscosity * std::pow(fluid_fraction,2) * rData.DN_DX(j,d) * rData.DDN_DDX[i](e,e); + GC += 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DN_DX(i,e) * rData.DDN_DDX[j](e,d); + CG += 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[i](d,e) * rData.DN_DX(j,e); + DG += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * rData.DN_DX(i,d) * fluid_fraction_gradient[e] * rData.DN_DX(j,e); + double AL = tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * AGradN[i] * rData.DDN_DDX[j](d,e); + double LA = tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[i](d,e) * AGradN[j]; + double AC = 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * AGradN[i] * rData.DDN_DDX[j](d,e); + double CA = 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[i](d,e) * AGradN[j]; + double DBetaA = 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * AGradN[j] * fluid_fraction_gradient[e] * rData.DN_DX(i,d); double RSigma = rData.N[i] * sigma(d,e) * rData.N[j]; - double ASigma = tau_one(d,d) * AGradN[i] * sigma(d,e) * rData.N[j] * fluid_fraction; - double ADBeta = 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * kin_viscosity * AGradN[i] * fluid_fraction_gradient[d] * rData.DN_DX(j,e); - double RRSigma = tau_one(d,d) * sigma(d,e) * rData.N[i] * sigma(e,d) * rData.N[j]; - double RSigmaA = tau_one(d,d) * fluid_fraction * sigma(d,e) * rData.N[i] * AGradN[j]; - double DD = tau_two * fluid_fraction * fluid_fraction * rData.DN_DX(i,d) * rData.DN_DX(j,e); + double AGBeta = tau_one(d,d) * fluid_fraction * viscosity * AGradN[i] * rData.DN_DX(j,d) * fluid_fraction_gradient[e]; + double ADBeta = 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * AGradN[i] * fluid_fraction_gradient[d] * rData.DN_DX(j,e); + double DD = tau_two * std::pow(fluid_fraction,2) * rData.DN_DX(i,d) * rData.DN_DX(j,e); double DU = tau_two * fluid_fraction * fluid_fraction_gradient[e] * rData.DN_DX(i,d) * rData.N[j]; - double DBetaA = 2.0 / 3.0 * kin_viscosity * fluid_fraction * tau_one(d,d) * AGradN[j] * fluid_fraction_gradient[e] * rData.DN_DX(i,d); + double GD = tau_two * fluid_fraction * fluid_fraction_gradient[d] * rData.DN_DX(j,e) * rData.N[i]; double GU = tau_two * rData.N[j] * rData.N[i] * fluid_fraction_gradient[d] * fluid_fraction_gradient[e]; - double GD = tau_two * fluid_fraction * rData.N[i] * fluid_fraction_gradient[d] * rData.DN_DX(j,e); - double AGBeta = tau_one(d,d) * fluid_fraction * kin_viscosity * AGradN[i] * (rData.DN_DX(j,d) * fluid_fraction_gradient[e]); - double GBetaA = tau_one(d,d) * fluid_fraction * kin_viscosity * AGradN[j] * rData.DN_DX(i,e) * fluid_fraction_gradient[d]; - double GBetaG = 0.0; - double GBetaD = 0.0; - double GBetaSigma = 0.0; + double GBetaA = tau_one(d,d) * fluid_fraction * viscosity * AGradN[j] * fluid_fraction_gradient[d] * rData.DN_DX(i,e); + double LL_diag_1 = 0.0; + double LL_diag_2 = 0.0; + double LL_2 = 0.0; + double LL_3 = 0.0; + double LL_4 = 0.0; + double LC_1 = 0.0; + double LC_2 = 0.0; + double LGBeta_1 = 0.0; + double LGBeta_2 = 0.0; + double LGBeta_3 = 0.0; + double LGBeta_4 = 0.0; + double LGBeta_5 = 0.0; + double LDBeta_1 = 0.0; + double LDBeta_2 = 0.0; + double CL_1 = 0.0; + double CL_2 = 0.0; + double CC = 0.0; + double CGBeta_1 = 0.0; + double CGBeta_2 = 0.0; + double CDBeta = 0.0; + double GBetaL_1 = 0.0; + double GBetaL_2 = 0.0; + double GBetaL_3 = 0.0; + double GBetaL_4 = 0.0; + double GBetaL_5 = 0.0; + double GBetaC_1 = 0.0; + double GBetaC_2 = 0.0; + double GBetaG_1 = 0.0; + double GBetaG_2 = 0.0; + double GBetaG_3 = 0.0; + double GBetaG_4 = 0.0; + double GBetaG_5 = 0.0; + double GBetaD_1 = 0.0; + double GBetaD_2 = 0.0; + double DBetaL_1 = 0.0; + double DBetaL_2 = 0.0; + double DBetaC = 0.0; double DBetaG = 0.0; double DBetaD = 0.0; - double DBetaSigma = 0.0; - double RGBeta = 0.0; - double RDBeta = 0.0; - GG += tau_one(d,d) * fluid_fraction * kin_viscosity * (fluid_fraction_gradient[d] * rData.DN_DX(i,e) * rData.DN_DX(j,e) + fluid_fraction_gradient[e] * rData.DN_DX(i,e) * rData.DN_DX(j,d)); - DG += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * kin_viscosity * rData.DN_DX(i,d) * fluid_fraction_gradient[e] * rData.DN_DX(j,e); for (unsigned int f = 0; f < Dim; f++){ - GBetaG += tau_one(d,d) * std::pow(kin_viscosity, 2) * fluid_fraction_gradient[d] * (rData.DN_DX(i,f) * rData.DN_DX(j,f) * fluid_fraction_gradient[e]); - GBetaG += tau_one(d,d) * std::pow(kin_viscosity, 2) * fluid_fraction_gradient[d] * (rData.DN_DX(j,f) * rData.DN_DX(i,e) * fluid_fraction_gradient[f]); - GBetaG += tau_one(d,d) * std::pow(kin_viscosity, 2) * fluid_fraction_gradient[f] * rData.DN_DX(i,f) * (rData.DN_DX(j,d) * fluid_fraction_gradient[e]); - GBetaD += 2.0 * (2.0 / 3.0 * tau_one(d,d) * std::pow(kin_viscosity, 2) * (fluid_fraction_gradient[f] * rData.DN_DX(i,f)) * fluid_fraction_gradient[d] * rData.DN_DX(j,e)); - DBetaG += 4.0 / 3.0 * tau_one(d,d) * std::pow(kin_viscosity, 2) * rData.DN_DX(i,d) * fluid_fraction_gradient[f] * rData.DN_DX(j,f) * fluid_fraction_gradient[e]; - DBetaD += 4.0 / 9.0 * tau_one(d,d) * std::pow(kin_viscosity, 2) * fluid_fraction_gradient[f] * fluid_fraction_gradient[f] * rData.DN_DX(i,d) * rData.DN_DX(j,e); - DBetaSigma += 2.0 / 3.0 * tau_one(d,d) * kin_viscosity * rData.DN_DX(i,d) * rData.N[j] * fluid_fraction_gradient[f] * sigma(f,e); - RDBeta += 2.0 / 3.0 * tau_one(d,d) * kin_viscosity * rData.N[i] * sigma(d,f) * fluid_fraction_gradient[f] * rData.DN_DX(j,e); - for (unsigned int g = 0; g < Dim; g++){ - GBetaSigma += tau_one(d,d) * kin_viscosity * (fluid_fraction_gradient[g] * rData.DN_DX(i,f) * sigma(f,e) + fluid_fraction_gradient[g] * rData.DN_DX(i,g) * sigma(d,f)); - for(unsigned int h = 0; h < Dim; h++){ - RGBeta += tau_one(d,d) * kin_viscosity * (rData.N[d] * sigma(d,f) * rData.DN_DX(i,f) * fluid_fraction_gradient[e] + rData.N[d] * fluid_fraction_gradient[h] * rData.DN_DX(i,h) * sigma(d,e)); - } + if (d == e){ + GBetaA += tau_one(d,d) * fluid_fraction * viscosity * AGradN[j] * fluid_fraction_gradient[f] * rData.DN_DX(i,f); + AGBeta += tau_one(d,d) * fluid_fraction * viscosity * AGradN[i] * fluid_fraction_gradient[f] * rData.DN_DX(j,f); + GS += fluid_fraction * viscosity * rData.DN_DX(i,f) * rData.DN_DX(j,f); + AL += tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[j](f,f) * AGradN[i]; + LA += tau_one(d,d) * std::pow(fluid_fraction,2) * viscosity * rData.DDN_DDX[i](f,f) * AGradN[j]; + LL_diag_1 += tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](f,f); + LL_diag_2 += rData.DDN_DDX[j](f,f); + LGBeta_2 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DDN_DDX[i](f,f); + LGBeta_3 += rData.DN_DX(j,f) * fluid_fraction_gradient[f]; + GBetaG_4 += tau_one(d,d) * std::pow(viscosity,2) * fluid_fraction_gradient[f] * rData.DN_DX(i,f); + GBetaG_5 += rData.DN_DX(j,f) * fluid_fraction_gradient[f]; + GBetaL_4 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * fluid_fraction_gradient[f] * rData.DN_DX(i,f); + GBetaL_5 += rData.DDN_DDX[j](f,f); } + LL_2 += tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](f,f) * rData.DDN_DDX[j](d,e); + LL_3 += tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](d,e) * rData.DDN_DDX[j](f,f); + LL_4 += tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](d,f) * rData.DDN_DDX[j](e,f); + LC_1 += 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](f,f) * rData.DDN_DDX[j](d,e); + LC_2 += 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](d,f) * rData.DDN_DDX[j](f,e); + CL_1 += 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](d,e) * rData.DDN_DDX[j](f,f); + CL_2 += 2.0 / 3.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](d,f) * rData.DDN_DDX[j](f,e); + CC += 4.0 / 9.0 * tau_one(d,d) * std::pow(fluid_fraction,2) * std::pow(viscosity,2) * rData.DDN_DDX[i](f,d) * rData.DDN_DDX[j](f,e); + LGBeta_1 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DDN_DDX[i](f,f) * rData.DN_DX(j,d) * fluid_fraction_gradient[e]; + LGBeta_4 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DDN_DDX[i](d,f) * rData.DN_DX(j,f) * fluid_fraction_gradient[e]; + LGBeta_5 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DDN_DDX[i](d,e) * fluid_fraction_gradient[f] * rData.DN_DX(j,f); + LDBeta_1 += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DN_DX(j,e) * fluid_fraction_gradient[d] * rData.DDN_DDX[i](f,f); + LDBeta_2 += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DN_DX(j,e) * fluid_fraction_gradient[f] * rData.DDN_DDX[i](d,f); + CGBeta_1 += 2.0 /3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DDN_DDX[i](d,f) * rData.DN_DX(j,f) * fluid_fraction_gradient[e]; + CGBeta_2 += 2.0 /3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DDN_DDX[i](d,e) * rData.DN_DX(j,f) * fluid_fraction_gradient[f]; + CDBeta += 4.0 / 9.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * fluid_fraction_gradient[f] * rData.DDN_DDX[i](d,f) * rData.DN_DX(j,e); + GBetaL_1 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * fluid_fraction_gradient[d] * rData.DN_DX(i,f) * rData.DDN_DDX[j](f,e); + GBetaL_2 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * fluid_fraction_gradient[d] * rData.DN_DX(i,e) * rData.DDN_DDX[j](f,f); + GBetaL_3 += tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * fluid_fraction_gradient[f] * rData.DN_DX(i,f) * rData.DDN_DDX[j](d,e); + GBetaC_1 += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * fluid_fraction_gradient[d] * rData.DN_DX(i,f) * rData.DDN_DDX[j](f,e); + GBetaC_2 += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * fluid_fraction_gradient[f] * rData.DN_DX(i,f) * rData.DDN_DDX[j](d,e); + DBetaL_1 += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DN_DX(i,d) * fluid_fraction_gradient[e] * rData.DDN_DDX[j](f,f); + DBetaL_2 += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DN_DX(i,d) * (fluid_fraction_gradient[f] * rData.DDN_DDX[j](f,e)); + DBetaC += 4.0 / 9.0 * tau_one(d,d) * fluid_fraction * std::pow(viscosity,2) * rData.DN_DX(i,d) * fluid_fraction_gradient[f] * rData.DDN_DDX[j](e,f); + DBetaG += 4.0 / 3.0 * tau_one(d,d) * std::pow(viscosity,2) * rData.DN_DX(i,d) * fluid_fraction_gradient[f] * rData.DN_DX(j,f) * fluid_fraction_gradient[e]; + GBetaG_1 += tau_one(d,d) * std::pow(viscosity,2) * fluid_fraction_gradient[d] * rData.DN_DX(i,f) * rData.DN_DX(j,f) * fluid_fraction_gradient[e]; + GBetaG_2 += tau_one(d,d) * std::pow(viscosity,2) * fluid_fraction_gradient[d] * rData.DN_DX(i,e) * rData.DN_DX(j,f) * fluid_fraction_gradient[f]; + GBetaG_3 += tau_one(d,d) * std::pow(viscosity,2) * fluid_fraction_gradient[f] * rData.DN_DX(i,f) * rData.DN_DX(j,d) * fluid_fraction_gradient[e]; + GBetaD_1 += 2.0 / 3.0 * tau_one(d,d) * std::pow(viscosity,2) * fluid_fraction_gradient[d] * rData.DN_DX(j,e) * fluid_fraction_gradient[f] * rData.DN_DX(i,f); + GBetaD_2 += 2.0 / 3.0 * tau_one(d,d) * std::pow(viscosity,2) * fluid_fraction_gradient[d] * rData.DN_DX(j,e) * fluid_fraction_gradient[f] * rData.DN_DX(i,f); + DBetaD += 4.0 / 9.0 * tau_one(d,d) * std::pow(viscosity, 2) * fluid_fraction_gradient[f] * fluid_fraction_gradient[f] * rData.DN_DX(i,d) * rData.DN_DX(j,e); } + double LL = (LL_diag_1 * LL_diag_2) + LL_2 + LL_3 + LL_4; + double LGBeta = LGBeta_1 + (LGBeta_2 * LGBeta_3) + LGBeta_4 + LGBeta_5; + double LC = LC_1 + LC_2; + double CL = CL_1 + CL_2; + double LDBeta = LDBeta_1 + LDBeta_2; + double CGBeta = CGBeta_1 + CGBeta_2; + double GBetaL = GBetaL_1 + GBetaL_2 + GBetaL_3 + (GBetaL_4 * GBetaL_5); + double GBetaC = GBetaC_1 + GBetaC_2; + double DBetaL = DBetaL_1 + DBetaL_2; + double GBetaG = GBetaG_1 + GBetaG_2 + GBetaG_3 + (GBetaG_4 * GBetaG_5); + double GBetaD = GBetaD_1 + GBetaD_2; + + LHS(row+d,col+e) += rData.Weight * (GS - DnuD + DD + DU + GU + GD + GBetaA - GBetaG + GBetaD - DBetaA + DBetaG - DBetaD - AGBeta + ADBeta + RSigma - AL + LA + AC - CA + LC + CL - CC - LL - LGBeta + LDBeta + CGBeta - CDBeta - GBetaL + GBetaC + DBetaL - DBetaC); - GR += tau_one(d,d) * fluid_fraction * rData.DN_DX(i,d) * sigma(d,e) * rData.N[j]; - RSigmaG += tau_one(d,d) * sigma(d,e) * rData.N[i] * rData.DN_DX(j,e); - LHS(row+d,col+e) += rData.Weight * (DD + DU + GU + GD + GBetaA - GBetaG + GBetaD + GBetaSigma - DBetaA + DBetaG - DBetaD - AGBeta + ADBeta - DBetaSigma + RGBeta - RDBeta + RSigma + ASigma - RRSigma - RSigmaA); - if (d == e){ - LHS(row+d,col+e) -= rData.Weight * (GBetaGDiag); - } } + double GGBeta = GGBeta_1 + GGBeta_2; + double GG = GG_1 + GG_2; - LHS(row+Dim,col+d) += rData.Weight * (GA + QD + GR - GGBeta + GDBeta + GD); + LHS(row+Dim,col+d) += rData.Weight * (GA - GL + GC + QD - GGBeta + GDBeta + GAlphaD); - LHS(row+d,col+Dim) += rData.Weight * (AG - P - GP - RSigmaG + GG - DG); + LHS(row+d,col+Dim) += rData.Weight * (AG + LG - CG - P - GP + GG - DG); } @@ -504,45 +923,130 @@ void AlternativeQSVMSDEMCoupled::AddVelocitySystem( for (unsigned int d = 0; d < Dim; ++d) { // v*BodyForce - double VF = rData.N[i] * (body_force[d]); + double VF = rData.N[i] * body_force[d]; // ( a * Grad(v) ) * TauOne * (Density * BodyForce - Projection) double AF = tau_one(d,d) * fluid_fraction * AGradN[i] * (body_force[d] - MomentumProj[d]); - double RSigmaF = 0.0; + double LF = 0.0; + double CF = 0.0; double GBetaF = 0.0; double DBetaF = 0.0; for (unsigned int e = 0; e < Dim; ++e){ - RSigmaF += tau_one(d,d) * sigma(d,e) * rData.N[i] * (body_force[e] - MomentumProj[e]); - DBetaF += 2.0 / 3.0 * tau_one(d,d) * kin_viscosity * rData.DN_DX(i,d) * fluid_fraction_gradient[e] * (body_force[e] - MomentumProj[e]); - GBetaF += tau_one(d,d) * kin_viscosity * (fluid_fraction_gradient[d] * rData.DN_DX(i,e)) * (body_force[e] - MomentumProj[e]); - for (unsigned int f = 0; f < Dim; ++f){ - GBetaF += tau_one(d,d) * kin_viscosity * (fluid_fraction_gradient[f] * rData.DN_DX(i,f)) * (body_force[e] - MomentumProj[e]); - } + LF += tau_one(d,d) * fluid_fraction * viscosity * rData.DDN_DDX[i](d,e) * (body_force[e] - MomentumProj[e]); + LF += tau_one(d,d) * fluid_fraction * viscosity * rData.DDN_DDX[i](e,e) * (body_force[d] - MomentumProj[d]); + CF += 2.0 / 3.0 * tau_one(d,d) * fluid_fraction * viscosity * rData.DDN_DDX[i](d,e) * (body_force[e] - MomentumProj[e]); + GBetaF += tau_one(d,d) * viscosity * fluid_fraction_gradient[d] * rData.DN_DX(i,e) * (body_force[e] - MomentumProj[e]); + GBetaF += tau_one(d,d) * viscosity * fluid_fraction_gradient[e] * rData.DN_DX(i,e) * (body_force[d] - MomentumProj[d]); + DBetaF += 2.0 / 3.0 * tau_one(d,d) * viscosity * rData.DN_DX(i,d) * fluid_fraction_gradient[e] * (body_force[e] - MomentumProj[e]); } // Grad(q) * TauOne * (Density * BodyForce - Projection) QAlphaF += tau_one(d,d) * rData.DN_DX(i,d) * fluid_fraction * (body_force[d] - MomentumProj[d]); - double VPhi = tau_two * rData.N[i] * fluid_fraction_gradient[d] * (mass_source - fluid_fraction_rate - MassProj); // OSS pressure subscale projection - double DPhi = rData.DN_DX(i,d) * tau_two * fluid_fraction * (mass_source - fluid_fraction_rate - MassProj); - rLocalRHS[row+d] += rData.Weight * (VF + AF + DPhi - RSigmaF + GBetaF - DBetaF + VPhi); + double VPhi = tau_two * rData.N[i] * fluid_fraction_gradient[d] * (mass_source - fluid_fraction_rate - MassProj); + double DPhi = tau_two * rData.DN_DX(i,d) * fluid_fraction * (mass_source - fluid_fraction_rate - MassProj); + rLocalRHS[row+d] += rData.Weight * (VF + AF + LF - CF + DPhi + GBetaF - DBetaF + VPhi); } double Q = rData.N[i] * (mass_source - fluid_fraction_rate); rLocalRHS[row+Dim] += rData.Weight * (QAlphaF + Q); // Grad(q) * TauOne * (Density * BodyForce) } - + // Adding reactive terms to the stabilization + if(!rData.UseOSS) + this->AddReactionStabilization(rData,LHS,rLocalRHS); // Write (the linearized part of the) local contribution into residual form (A*dx = b - A*x) array_1d values; this->GetCurrentValuesVector(rData,values); noalias(rLocalRHS) -= prod(LHS, values); - /* Viscous contribution (with symmetric gradient 2*nu*{E(u) - 1/3 Tr(E)} ) - * For a generic (potentially non-linear) constitutive law, one cannot assume that RHS = F - LHS*current_values. - * Because of this, the AddViscousTerm function manages both the LHS and the RHS. - */ - this->AddViscousTerm(rData,LHS,rLocalRHS); - noalias(rLocalLHS) += LHS; } +template +void AlternativeQSVMSDEMCoupled::CalculateMassMatrix(MatrixType& rMassMatrix, + const ProcessInfo& rCurrentProcessInfo) +{ + // Resize and intialize output + if (rMassMatrix.size1() != LocalSize) + rMassMatrix.resize(LocalSize, LocalSize, false); + + noalias(rMassMatrix) = ZeroMatrix(LocalSize, LocalSize); + + if (!TElementData::ElementManagesTimeIntegration) { + // Get Shape function data + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + DenseVector> shape_function_second_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); + const unsigned int number_of_gauss_points = gauss_weights.size(); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + // Iterate over integration points to evaluate local contribution + for (unsigned int g = 0; g < number_of_gauss_points; g++) { + this->UpdateIntegrationPointDataSecondDerivatives( + data, g, gauss_weights[g], + row(shape_functions, g),shape_derivatives[g],shape_function_second_derivatives[g]); + + this->AddMassLHS(data, rMassMatrix); + } + } +} + +template +void AlternativeQSVMSDEMCoupled::CalculateLocalVelocityContribution(MatrixType& rDampMatrix, + VectorType& rRightHandSideVector, + const ProcessInfo& rCurrentProcessInfo) +{ + // Resize and intialize output + if( rDampMatrix.size1() != LocalSize ) + rDampMatrix.resize(LocalSize,LocalSize,false); + + if( rRightHandSideVector.size() != LocalSize ) + rRightHandSideVector.resize(LocalSize,false); + + noalias(rDampMatrix) = ZeroMatrix(LocalSize,LocalSize); + noalias(rRightHandSideVector) = ZeroVector(LocalSize); + + if (!TElementData::ElementManagesTimeIntegration) { + // Get Shape function data + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + DenseVector> shape_function_second_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + const unsigned int number_of_gauss_points = gauss_weights.size(); + + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + // Iterate over integration points to evaluate local contribution + for (unsigned int g = 0; g < number_of_gauss_points; g++) { + const auto& r_dndx = shape_derivatives[g]; + this->UpdateIntegrationPointDataSecondDerivatives( + data, g, gauss_weights[g], + row(shape_functions, g),r_dndx, shape_function_second_derivatives[g]); + this->AddVelocitySystem(data, rDampMatrix, rRightHandSideVector); + } + } +} + +template < class TElementData > +void AlternativeQSVMSDEMCoupled::CalculateResistanceTensor( + const TElementData& rData) +{ + BoundedMatrix& rsigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; + BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); + + rsigma = permeability; +} + template< class TElementData > void AlternativeQSVMSDEMCoupled::AddMassLHS( TElementData& rData, @@ -580,17 +1084,15 @@ void AlternativeQSVMSDEMCoupled::MassProjTerm( double &rMassRHS) const { const auto velocities = rData.Velocity; - const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); - const auto fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); const double mass_source = this->GetAtCoordinate(rData.MassSource, rData.N); const double fluid_fraction_rate = this->GetAtCoordinate(rData.FluidFractionRate, rData.N); + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); // Compute this node's contribution to the residual (evaluated at integration point) - for (unsigned int i = 0; i < NumNodes; i++) { - for (unsigned int d = 0; d < Dim; ++d) - { - rMassRHS -= fluid_fraction * rData.DN_DX(i, d) * velocities(i, d) + fluid_fraction_gradient[d] * rData.N[i] * velocities(i,d); + for (unsigned int i = 0; i < NumNodes; i++){ + for (unsigned int d = 0; d < Dim; d++){ + rMassRHS -= (fluid_fraction_gradient[d] * rData.N[i] * velocities(i,d) + fluid_fraction * rData.DN_DX(i,d) * velocities(i,d)); } } rMassRHS += mass_source - fluid_fraction_rate; @@ -605,41 +1107,103 @@ void AlternativeQSVMSDEMCoupled::CalculateTau( { constexpr double c1 = 8.0; constexpr double c2 = 2.0; + const int p = mInterpolationOrder; double inv_tau; double inv_tau_NS; + //double spectral_radius = 0.0; const double h = rData.ElementSize; const double density = this->GetAtCoordinate(rData.Density,rData.N); const double viscosity = this->GetAtCoordinate(rData.EffectiveViscosity,rData.N); - double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); + const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction,rData.N); + MatrixType sigma = ZeroMatrix(Dim+1, Dim+1); BoundedMatrix I = IdentityMatrix(Dim, Dim); - array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); double velocity_modulus = 0.0; double fluid_fraction_gradient_modulus = 0.0; - double sigma_term = 0.0; + for (unsigned int d = 0; d < Dim; d++){ velocity_modulus += Velocity[d] * Velocity[d]; fluid_fraction_gradient_modulus += std::pow(fluid_fraction_gradient[d],2); - for (unsigned int e = d; e < Dim; e++){ - sigma_term += std::pow(sigma(d,e),2); - } + sigma(d,d) = mViscousResistanceTensor[rData.IntegrationPointIndex](d,d); } + // This last term does not exist physically and it is included to do the spectral radius taking into account the inverse Gamma + // whose size is (d+1,d+1) + double velocity_norm = std::sqrt(velocity_modulus); double fluid_fraction_gradient_norm = std::sqrt(fluid_fraction_gradient_modulus); + double c_alpha = fluid_fraction + h / c1 * fluid_fraction_gradient_norm; - inv_tau = (c1 * viscosity / (h*h) + density * (c2 * velocity_norm / h )) * c_alpha + std::sqrt(sigma_term); - inv_tau_NS = c1 * viscosity / (h*h) + density * (c2 * velocity_norm / h ) + std::sqrt(sigma_term); - double tau_one = 1 / inv_tau; - double tau_one_NS = 1 / inv_tau_NS; + inv_tau_NS = c1 * viscosity / std::pow(h/(p*p),2.0) + density * (c2 * velocity_norm / (h/p) ); + double tau_one_NS = 1.0 / inv_tau_NS; + + inv_tau = inv_tau_NS * c_alpha; + double tau_one = 1.0 / (inv_tau + sigma(0,0)); + TauOne = tau_one * I; - TauTwo = h * h / (c1 * fluid_fraction * tau_one_NS); + TauTwo = std::pow(h/p,2.0) / (c1 * fluid_fraction * tau_one_NS); +} + +template< class TElementData > +void AlternativeQSVMSDEMCoupled::CalculateProjections(const ProcessInfo &rCurrentProcessInfo) +{ + // Get Shape function data + + DenseVector> ShapeFunctionSecondDerivatives; + Vector GaussWeights; + Matrix ShapeFunctions; + ShapeFunctionDerivativesArrayType ShapeDerivatives; + this->CalculateGeometryData(GaussWeights,ShapeFunctions,ShapeDerivatives); + const long unsigned int NumGauss = GaussWeights.size(); + + GeometryType& r_geometry = this->GetGeometry(); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + ShapeFunctionSecondDerivatives,this->GetGeometry(),this->GetIntegrationMethod()); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + array_1d momentum_rhs = ZeroVector(NumNodes*Dim); + VectorType MassRHS = ZeroVector(NumNodes); + VectorType NodalArea = ZeroVector(NumNodes); + + for (unsigned int g = 0; g < NumGauss; g++) + { + this->UpdateIntegrationPointDataSecondDerivatives(data, g, GaussWeights[g], row(ShapeFunctions, g), ShapeDerivatives[g],ShapeFunctionSecondDerivatives[g]); + + array_1d MomentumRes = ZeroVector(3); + double MassRes = 0.0; + //array_1d convective_velocity = this->GetAtCoordinate(data.Velocity,data.N) - this->GetAtCoordinate(data.MeshVelocity,data.N); + array_1d convective_velocity = this->FullConvectiveVelocity(data); + this->MomentumProjTerm(data, convective_velocity, MomentumRes); + this->MassProjTerm(data,MassRes); + + for (unsigned int i = 0; i < NumNodes; i++) + { + double W = data.Weight*data.N[i]; + unsigned int row = i*Dim; + for (unsigned int d = 0; d < Dim; d++) + momentum_rhs[row+d] += W*MomentumRes[d]; + MassRHS[i] += W*MassRes; + NodalArea[i] += data.Weight*data.N[i]; + } + } + + // Add carefully to nodal variables to avoid OpenMP race condition + for (SizeType i = 0; i < NumNodes; ++i) + { + r_geometry[i].SetLock(); // So it is safe to write in the node in OpenMP + array_1d& rMomValue = r_geometry[i].FastGetSolutionStepValue(ADVPROJ); + unsigned int row = i*Dim; + for (unsigned int d = 0; d < Dim; d++) + rMomValue[d] += momentum_rhs[row+d]; + r_geometry[i].FastGetSolutionStepValue(NODAL_AREA) += NodalArea[i]; + r_geometry[i].FastGetSolutionStepValue(DIVPROJ) += MassRHS[i]; + r_geometry[i].UnSetLock(); // Free the node for other threads + } } template< class TElementData > @@ -649,7 +1213,9 @@ void AlternativeQSVMSDEMCoupled::SubscaleVelocity( { BoundedMatrix tau_one = ZeroMatrix(Dim, Dim); double tau_two; - array_1d convective_velocity = this->GetAtCoordinate(rData.Velocity,rData.N) - this->GetAtCoordinate(rData.MeshVelocity,rData.N); + + //array_1d convective_velocity = this->GetAtCoordinate(rData.Velocity,rData.N) - this->GetAtCoordinate(rData.MeshVelocity,rData.N); + array_1d convective_velocity = this->FullConvectiveVelocity(rData); this->CalculateTau(rData,convective_velocity,tau_one,tau_two); array_1d Residual = ZeroVector(3); @@ -670,7 +1236,7 @@ void AlternativeQSVMSDEMCoupled::SubscalePressure( { BoundedMatrix tau_one = ZeroMatrix(Dim, Dim); double tau_two; - array_1d convective_velocity = + const array_1d convective_velocity = this->GetAtCoordinate(rData.Velocity, rData.N) - this->GetAtCoordinate(rData.MeshVelocity, rData.N); this->CalculateTau(rData, convective_velocity, tau_one, tau_two); @@ -685,6 +1251,58 @@ void AlternativeQSVMSDEMCoupled::SubscalePressure( rPressureSubscale = tau_two*Residual; } +template< class TElementData > +array_1d AlternativeQSVMSDEMCoupled::FullConvectiveVelocity( + const TElementData& rData) const +{ + array_1d convective_velocity = this->GetAtCoordinate(rData.Velocity,rData.N) - this->GetAtCoordinate(rData.MeshVelocity,rData.N); + //Adding subscale term componentwise because return type is of size 3, but subscale is of size Dim + const array_1d& r_predicted_subscale = mPredictedSubscaleVelocity[rData.IntegrationPointIndex]; + + for (unsigned int d = 0; d < Dim; d++) { + convective_velocity[d] += r_predicted_subscale[d]; + } + + return convective_velocity; +} + +template< class TElementData > +void AlternativeQSVMSDEMCoupled::UpdateSubscaleVelocity( + const TElementData& rData) +{ + array_1d predicted_subscale_velocity; + + array_1d previous_velocity = mPreviousVelocity[rData.IntegrationPointIndex]; + + //for (size_t i = 0; i < NumNodes; i++) { + array_1d subscale_velocity_on_previous_iteration = mPredictedSubscaleVelocity[rData.IntegrationPointIndex]; + + array_1d v_d = ZeroVector(3); + + for (unsigned int d = 0; d < Dim; d++) + v_d[d] = previous_velocity[d] + subscale_velocity_on_previous_iteration[d]; + + // Part of the residual that does not depend on the subscale + array_1d static_residual = ZeroVector(3); + + if (!rData.UseOSS) + this->AlgebraicMomentumResidual(rData,v_d,static_residual); + else + this->OrthogonalMomentumResidual(rData,v_d,static_residual); + + + BoundedMatrix tau_one = ZeroMatrix(Dim, Dim); + double tau_two; + + this->CalculateTau(rData,v_d,tau_one,tau_two); + + for (unsigned int d = 0; d < Dim; d++) + predicted_subscale_velocity[d] = tau_one(d,d) * static_residual[d]; + + noalias(mPredictedSubscaleVelocity[rData.IntegrationPointIndex]) = predicted_subscale_velocity; + +} + /////////////////////////////////////////////////////////////////////////////////////////////////// // Private functions /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -713,6 +1331,9 @@ template class AlternativeQSVMSDEMCoupled >; template class AlternativeQSVMSDEMCoupled >; template class AlternativeQSVMSDEMCoupled< QSVMSDEMCoupledData<2,4> >; +template class AlternativeQSVMSDEMCoupled< QSVMSDEMCoupledData<2,6> >; +template class AlternativeQSVMSDEMCoupled< QSVMSDEMCoupledData<2,9> >; + template class AlternativeQSVMSDEMCoupled< QSVMSDEMCoupledData<3,8> >; +template class AlternativeQSVMSDEMCoupled< QSVMSDEMCoupledData<3,27> >; } - diff --git a/applications/FluidDynamicsApplication/custom_elements/alternative_qs_vms_dem_coupled.h b/applications/FluidDynamicsApplication/custom_elements/alternative_qs_vms_dem_coupled.h index b98df7f40e52..e56a1ee03acf 100644 --- a/applications/FluidDynamicsApplication/custom_elements/alternative_qs_vms_dem_coupled.h +++ b/applications/FluidDynamicsApplication/custom_elements/alternative_qs_vms_dem_coupled.h @@ -100,6 +100,8 @@ class AlternativeQSVMSDEMCoupled : public QSVMS /// Type for an array of shape function gradient matrices typedef GeometryType::ShapeFunctionsGradientsType ShapeFunctionDerivativesArrayType; + typedef GeometryType::ShapeFunctionsSecondDerivativesType ShapeFunctionsSecondDerivativesType; + constexpr static unsigned int Dim = QSVMS::Dim; constexpr static unsigned int NumNodes = QSVMS::NumNodes; constexpr static unsigned int BlockSize = QSVMS::BlockSize; @@ -179,6 +181,11 @@ class AlternativeQSVMSDEMCoupled : public QSVMS GeometryType::Pointer pGeom, Properties::Pointer pProperties) const override; + + void Initialize(const ProcessInfo& rCurrentProcessInfo) override; + + GeometryData::IntegrationMethod GetIntegrationMethod() const override; + ///@} ///@name Access ///@{ @@ -218,7 +225,11 @@ class AlternativeQSVMSDEMCoupled : public QSVMS ///@name Protected member Variables ///@{ - + int mInterpolationOrder = 1; + DenseVector > mViscousResistanceTensor; + // Velocity subscale history, stored at integration points + DenseVector< array_1d > mPredictedSubscaleVelocity; + DenseVector< array_1d > mPreviousVelocity; ///@} ///@name Protected Operators ///@{ @@ -230,6 +241,8 @@ class AlternativeQSVMSDEMCoupled : public QSVMS // Protected interface of FluidElement //////////////////////////////////// + /// Determine the shape second derivative in the gauss point + void AlgebraicMomentumResidual( const TElementData& rData, const array_1d &rConvectionVelocity, @@ -244,6 +257,11 @@ class AlternativeQSVMSDEMCoupled : public QSVMS TElementData& rData, MatrixType &rMassMatrix); + void AddReactionStabilization( + TElementData& rData, + BoundedMatrix& rLHS, + VectorType& rLocalRHS); + void AddViscousTerm( const TElementData& rData, BoundedMatrix& rLHS, @@ -256,15 +274,36 @@ class AlternativeQSVMSDEMCoupled : public QSVMS BoundedMatrix &TauOne, double &TauTwo) const; + void CalculateProjections( + const ProcessInfo &rCurrentProcessInfo) override; + + void UpdateIntegrationPointDataSecondDerivatives( + TElementData& rData, + unsigned int IntegrationPointIndex, + double Weight, + const typename TElementData::MatrixRowType& rN, + const typename TElementData::ShapeDerivativesType& rDN_DX, + const typename TElementData::ShapeFunctionsSecondDerivativesType& rDDN_DDX) const; + void AddVelocitySystem( TElementData& rData, MatrixType &rLocalLHS, VectorType &rLocalRHS) override; + void CalculateMassMatrix(MatrixType& rMassMatrix, + const ProcessInfo& rCurrentProcessInfo) override; + + void CalculateLocalVelocityContribution(MatrixType& rDampMatrix, + VectorType& rRightHandSideVector, + const ProcessInfo& rCurrentProcessInfo) override; + void AddMassLHS( TElementData& rData, MatrixType& rMassMatrix) override; + void CalculateResistanceTensor( + const TElementData& rData); + void MassProjTerm( const TElementData& rData, double &rMassRHS) const override; @@ -281,6 +320,29 @@ class AlternativeQSVMSDEMCoupled : public QSVMS const Variable>& rVariable, array_1d& rOutput, const ProcessInfo& rCurrentProcessInfo) override; + void CalculateOnIntegrationPoints( + const Variable>& rVariable, + std::vector>& rOutput, + const ProcessInfo& rCurrentProcessInfo) override; + + void CalculateOnIntegrationPoints( + const Variable& rVariable, + std::vector& rOutput, + const ProcessInfo& rCurrentProcessInfo) override; + + void CalculateOnIntegrationPoints( + Variable const& rVariable, + std::vector& rValues, + ProcessInfo const& rCurrentProcessInfo) override; + + void InitializeNonLinearIteration(const ProcessInfo& rCurrentProcessInfo) override; + + void FinalizeNonLinearIteration(const ProcessInfo& rCurrentProcessInfo) override; + + void UpdateSubscaleVelocity(const TElementData& rData); + + array_1d FullConvectiveVelocity(const TElementData& rData) const; + ///@} ///@name Protected Access ///@{ diff --git a/applications/FluidDynamicsApplication/custom_elements/d_vms.cpp b/applications/FluidDynamicsApplication/custom_elements/d_vms.cpp index e92f7071b706..a73166a5bc1a 100644 --- a/applications/FluidDynamicsApplication/custom_elements/d_vms.cpp +++ b/applications/FluidDynamicsApplication/custom_elements/d_vms.cpp @@ -923,6 +923,9 @@ template class DVMS< QSVMSDEMCoupledData<2,3> >; template class DVMS< QSVMSDEMCoupledData<3,4> >; template class DVMS< QSVMSDEMCoupledData<2,4> >; +template class DVMS< QSVMSDEMCoupledData<2,6> >; +template class DVMS< QSVMSDEMCoupledData<2,9> >; template class DVMS< QSVMSDEMCoupledData<3,8> >; +template class DVMS< QSVMSDEMCoupledData<3,27> >; } // namespace Kratos diff --git a/applications/FluidDynamicsApplication/custom_elements/d_vms_dem_coupled.cpp b/applications/FluidDynamicsApplication/custom_elements/d_vms_dem_coupled.cpp index 28d8a3a66d5c..19b1e91047a9 100644 --- a/applications/FluidDynamicsApplication/custom_elements/d_vms_dem_coupled.cpp +++ b/applications/FluidDynamicsApplication/custom_elements/d_vms_dem_coupled.cpp @@ -94,17 +94,135 @@ Element::Pointer DVMSDEMCoupled::Create( /////////////////////////////////////////////////////////////////////////////////////////////////// // Input and output +template< class TElementData > +void DVMSDEMCoupled::CalculateOnIntegrationPoints( + const Variable& rVariable, + std::vector& rOutput, + const ProcessInfo& rCurrentProcessInfo) +{ + const GeometryType::IntegrationPointsArrayType integration_points = this->GetGeometry().IntegrationPoints(this->GetIntegrationMethod()); + const SizeType number_of_integration_points = integration_points.size(); + + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + + if (rOutput.size() != number_of_integration_points) + rOutput.resize(number_of_integration_points); + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + for (unsigned int g = 0; g < number_of_integration_points; g++ ) { + data.UpdateGeometryValues(g, gauss_weights[g], row(shape_functions, g),shape_derivatives[g]); + if (rVariable == PRESSURE) { + const auto& r_pressure = data.Pressure; + double value = this->GetAtCoordinate(r_pressure,data.N); + rOutput[g] = value; + } + } +} + +template< class TElementData > +void DVMSDEMCoupled::CalculateOnIntegrationPoints( + const Variable& rVariable, + std::vector& rValues, + const ProcessInfo& rCurrentProcessInfo) +{ + const GeometryType::IntegrationPointsArrayType integration_points = this->GetGeometry().IntegrationPoints(this->GetIntegrationMethod()); + const SizeType number_of_integration_points = integration_points.size(); + + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + + if (rValues.size() != number_of_integration_points) + rValues.resize(number_of_integration_points); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + for (unsigned int g = 0; g < number_of_integration_points; g++ ) { + data.UpdateGeometryValues(g, gauss_weights[g], row(shape_functions, g),shape_derivatives[g]); + Matrix value = ZeroMatrix(Dim, Dim); + if (rVariable == VELOCITY_GRADIENT) { + const auto& r_velocity = data.Velocity; + for (unsigned int i = 0; i < NumNodes; i++) { + for (unsigned int d = 0; d < Dim; d++) { + for (unsigned int e = 0; e < Dim; e++) + value(d,e) += data.DN_DX(i,d) * r_velocity(i,e); + } + } + } + rValues[g] = value; + } +} + +template< class TElementData > +void DVMSDEMCoupled::CalculateOnIntegrationPoints( + const Variable>& rVariable, + std::vector>& rOutput, + const ProcessInfo& rCurrentProcessInfo) +{ + const GeometryType::IntegrationPointsArrayType integration_points = this->GetGeometry().IntegrationPoints(this->GetIntegrationMethod()); + const SizeType number_of_integration_points = integration_points.size(); + + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + + if (rOutput.size() != number_of_integration_points) + rOutput.resize(number_of_integration_points); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + for (unsigned int g = 0; g < number_of_integration_points; g++ ) { + data.UpdateGeometryValues(g, gauss_weights[g], row(shape_functions, g),shape_derivatives[g]); + array_1d value(3,0.0); + if (rVariable == VELOCITY) { + const auto& r_velocity = data.Velocity; + value = this->GetAtCoordinate(r_velocity,data.N); + } + if (rVariable == BODY_FORCE) { + value = this->GetAtCoordinate(data.BodyForce,data.N); + } + if (rVariable == PRESSURE_GRADIENT){ + const auto& r_pressure = data.Pressure; + for (unsigned int i = 0; i < NumNodes; i++) { + for (unsigned int d = 0; d < Dim; d++) { + value[d] += r_pressure[i] * data.DN_DX(i,d); + } + } + } + rOutput[g] = value; + } +} + template void DVMSDEMCoupled::Initialize(const ProcessInfo& rCurrentProcessInfo) { // Base class does things with constitutive law here. DVMS::Initialize(rCurrentProcessInfo); + if(Dim == 2){ + if (NumNodes == 9 || NumNodes == 6 || NumNodes == 4) + mInterpolationOrder = 2; + } + else if(Dim == 3){ + if (NumNodes == 10 || NumNodes == 27) + mInterpolationOrder = 2; + } + const unsigned int number_of_gauss_points = this->GetGeometry().IntegrationPointsNumber(this->GetIntegrationMethod()); // The prediction is updated before each non-linear iteration: // It is not stored in a restart and can be safely initialized. - mPreviousVelocity.resize(number_of_gauss_points); + //mPreviousVelocity.resize(number_of_gauss_points); // The old velocity may be already defined (if restarting) // and we want to keep the loaded values in that case. @@ -115,8 +233,13 @@ void DVMSDEMCoupled::Initialize(const ProcessInfo& rCurrentProcess mPreviousVelocity[g] = ZeroVector(Dim); } - mPredictedSubscaleVelocity.resize(number_of_gauss_points); - for (unsigned int g = 0; g < number_of_gauss_points; g++) + if (mPredictedSubscaleVelocity.size() != number_of_gauss_points) + { + mPredictedSubscaleVelocity.resize(number_of_gauss_points); + for (unsigned int g = 0; g < number_of_gauss_points; g++) + mPredictedSubscaleVelocity[g] = ZeroVector(Dim); + } + // The old velocity may be already defined (if restarting) // and we want to keep the loaded values in that case. if (mOldSubscaleVelocity.size() != number_of_gauss_points) @@ -125,70 +248,112 @@ void DVMSDEMCoupled::Initialize(const ProcessInfo& rCurrentProcess for (unsigned int g = 0; g < number_of_gauss_points; g++) mOldSubscaleVelocity[g] = ZeroVector(Dim); } + + // The prediction is updated before each non-linear iteration: + // It is not stored in a restart and can be safely initialized. + + // The old velocity may be already defined (if restarting) + // and we want to keep the loaded values in that case. + if (mViscousResistanceTensor.size() != number_of_gauss_points) + { + mViscousResistanceTensor.resize(number_of_gauss_points); + for (unsigned int g = 0; g < number_of_gauss_points; g++) + mViscousResistanceTensor[g] = ZeroMatrix(Dim,Dim); + } +} + +template< class TElementData > +GeometryData::IntegrationMethod DVMSDEMCoupled::GetIntegrationMethod() const +{ + if(mInterpolationOrder == 1) + return GeometryData::IntegrationMethod::GI_GAUSS_2; + else + return GeometryData::IntegrationMethod::GI_GAUSS_3; } template -void DVMSDEMCoupled::FinalizeSolutionStep(const ProcessInfo& rCurrentProcessInfo) +void DVMSDEMCoupled::InitializeNonLinearIteration(const ProcessInfo& rCurrentProcessInfo) { // Get Shape function data Vector gauss_weights; Matrix shape_functions; ShapeFunctionDerivativesArrayType shape_function_derivatives; + DenseVector> shape_function_second_derivatives; this->CalculateGeometryData(gauss_weights,shape_functions,shape_function_derivatives); const unsigned int number_of_integration_points = gauss_weights.size(); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); TElementData data; data.Initialize(*this,rCurrentProcessInfo); - for (unsigned int g = 0; g < number_of_integration_points; g++) { - this->UpdateIntegrationPointData(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g]); + this->UpdateIntegrationPointDataSecondDerivatives(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g],shape_function_second_derivatives[g]); - // Not doing the update "in place" because SubscaleVelocity uses mOldSubscaleVelocity - array_1d UpdatedValue = ZeroVector(3); - this->SubscaleVelocity(data,UpdatedValue); - array_1d& r_value = mOldSubscaleVelocity[g]; - for (unsigned int d = 0; d < Dim; d++) { - r_value[d] = UpdatedValue[d]; - } + this->CalculateResistanceTensor(data); } } template -void DVMSDEMCoupled::InitializeNonLinearIteration(const ProcessInfo& rCurrentProcessInfo) +void DVMSDEMCoupled::FinalizeNonLinearIteration(const ProcessInfo& rCurrentProcessInfo) { // Get Shape function data Vector gauss_weights; Matrix shape_functions; ShapeFunctionDerivativesArrayType shape_function_derivatives; + DenseVector> shape_function_second_derivatives; this->CalculateGeometryData(gauss_weights,shape_functions,shape_function_derivatives); const unsigned int number_of_integration_points = gauss_weights.size(); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); TElementData data; data.Initialize(*this,rCurrentProcessInfo); - for (unsigned int g = 0; g < number_of_integration_points; g++) { - this->UpdateIntegrationPointData(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g]); + this->UpdateIntegrationPointDataSecondDerivatives(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g],shape_function_second_derivatives[g]); - this->UpdateSubscaleVelocityPrediction(data); + this->UpdateSubscaleVelocity(data); } } template -void DVMSDEMCoupled::FinalizeNonLinearIteration(const ProcessInfo& rCurrentProcessInfo) +void DVMSDEMCoupled::UpdateIntegrationPointDataSecondDerivatives( + TElementData& rData, + unsigned int IntegrationPointIndex, + double Weight, + const typename TElementData::MatrixRowType& rN, + const typename TElementData::ShapeDerivativesType& rDN_DX, + const typename TElementData::ShapeFunctionsSecondDerivativesType& rDDN_DDX) const +{ + this->UpdateIntegrationPointData(rData, IntegrationPointIndex, Weight, rN, rDN_DX); + rData.UpdateSecondDerivativesValues(rDDN_DDX); +} + +template +void DVMSDEMCoupled::FinalizeSolutionStep(const ProcessInfo& rCurrentProcessInfo) { // Get Shape function data Vector gauss_weights; Matrix shape_functions; ShapeFunctionDerivativesArrayType shape_function_derivatives; + DenseVector> shape_function_second_derivatives; this->CalculateGeometryData(gauss_weights,shape_functions,shape_function_derivatives); const unsigned int number_of_integration_points = gauss_weights.size(); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); TElementData data; data.Initialize(*this,rCurrentProcessInfo); + array_1d UpdatedValue; for (unsigned int g = 0; g < number_of_integration_points; g++) { - this->UpdateIntegrationPointData(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g]); + this->UpdateIntegrationPointDataSecondDerivatives(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g],shape_function_second_derivatives[g]); - this->UpdateSubscaleVelocity(data); + // Not doing the update "in place" because SubscaleVelocity uses mOldSubscaleVelocity + UpdatedValue = ZeroVector(3); + this->SubscaleVelocity(data,UpdatedValue); + array_1d& r_value = mOldSubscaleVelocity[g]; + for (unsigned int d = 0; d < Dim; d++) { + r_value[d] = UpdatedValue[d]; + } } } @@ -226,27 +391,33 @@ void DVMSDEMCoupled::AlgebraicMomentumResidual( const double density = this->GetAtCoordinate(rData.Density,rData.N); const double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); - const auto& r_body_forces = rData.BodyForce; const auto& r_velocities = rData.Velocity; const auto& r_pressures = rData.Pressure; - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); + const auto& body_force = this->GetAtCoordinate(rData.BodyForce, rData.N); - sigma *= viscosity; + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; + Vector sigma_U, grad_div_u, div_sym_grad_u; for (unsigned int i = 0; i < NumNodes; i++) { - const array_1d& r_acceleration = rGeom[i].FastGetSolutionStepValue(ACCELERATION); - Vector sigma_U = ZeroVector(Dim); + const array_1d& r_acceleration = rGeom[i].FastGetSolutionStepValue(ACCELERATION); + array_1d sigma_U = ZeroVector(Dim); + grad_div_u = ZeroVector(Dim); + div_sym_grad_u = ZeroVector(Dim); for (unsigned int d = 0; d < Dim; d++) { for (unsigned int e = 0; e < Dim; e++){ sigma_U[d] += sigma(d,e) * rData.N[i] * r_velocities(i,e); + grad_div_u[d] += rData.DDN_DDX[i](d,e) * r_velocities(i,e); + if (d == e) + div_sym_grad_u[d] += rData.DDN_DDX[i](e,e) * r_velocities(i,d); + else + div_sym_grad_u[d] += 1.0/2.0 * (rData.DDN_DDX[i](e,d) * r_velocities(i,e) + rData.DDN_DDX[i](e,e) * r_velocities(i,d)); } - rResidual[d] += density * ( rData.N[i]*(r_body_forces(i,d) - r_acceleration[d]) - convection[i]*r_velocities(i,d)) - rData.DN_DX(i,d)*r_pressures[i] - sigma_U[d]; + rResidual[d] += density * ( rData.N[i]*(/*r_body_forces(i,d)*/ - r_acceleration[d]) - convection[i]*r_velocities(i,d)) + 2.0 * viscosity * div_sym_grad_u[d] - 2.0/3.0 * viscosity * grad_div_u[d] - rData.DN_DX(i,d) * r_pressures[i] - sigma_U[d]; } } + for (unsigned int d = 0; d < Dim; d++) + rResidual[d] += density * body_force[d]; } template< class TElementData > @@ -260,37 +431,130 @@ void DVMSDEMCoupled::MomentumProjTerm( const double density = this->GetAtCoordinate(rData.Density,rData.N); const double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); + const auto& body_force = this->GetAtCoordinate(rData.BodyForce, rData.N); - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); - - sigma *= viscosity; + const auto r_velocities = rData.Velocity; + const auto r_pressures = rData.Pressure; + Vector grad_div_u, div_sym_grad_u; for (unsigned int i = 0; i < NumNodes; i++) { - array_1d sigma_u = ZeroVector(Dim); + grad_div_u = ZeroVector(Dim); + div_sym_grad_u = ZeroVector(Dim); for (unsigned int d = 0; d < Dim; d++) { for (unsigned int e = 0; e < Dim; e++){ - sigma_u[d] += sigma(d,e) * rData.N[i] * rData.Velocity(i,e); + grad_div_u[d] += rData.DDN_DDX[i](d,e) * r_velocities(i,e); + if (d == e) + div_sym_grad_u[d] += rData.DDN_DDX[i](e,e) * r_velocities(i,d); + else + div_sym_grad_u[d] += 1.0/2.0 * (rData.DDN_DDX[i](e,d) * r_velocities(i,e) + rData.DDN_DDX[i](e,e) * r_velocities(i,d)); } - rMomentumRHS[d] += density * ( rData.N[i]*(rData.BodyForce(i,d) /*- rAcc[d]*/) - AGradN[i]*rData.Velocity(i,d)) - rData.DN_DX(i,d)*rData.Pressure[i] - sigma_u[d]; + rMomentumRHS[d] += density * (- AGradN[i]*r_velocities(i,d)) + 2.0 * viscosity * div_sym_grad_u[d] - 2.0/3.0 * viscosity * grad_div_u[d] - rData.DN_DX(i,d) * r_pressures[i]; } } + for (unsigned int d = 0; d < Dim; d++) + rMomentumRHS[d] += density * body_force[d]; } +template +void DVMSDEMCoupled::AddReactionStabilization( + TElementData& rData, + BoundedMatrix& rLHS, + VectorType& rLocalRHS) +{ + + const double density = this->GetAtCoordinate(rData.Density, rData.N); + + BoundedMatrix tau_one = ZeroMatrix(Dim, Dim); + double tau_two; + const array_1d convective_velocity = this->FullConvectiveVelocity(rData); + + this->CalculateStabilizationParameters(rData, convective_velocity, tau_one, tau_two); + + array_1d body_force = density * this->GetAtCoordinate(rData.BodyForce, rData.N); + + Vector AGradN; + this->ConvectionOperator(AGradN, convective_velocity, rData.DN_DX); // Get a * grad(Ni) + + AGradN *= density; + + const double dt = rData.DeltaTime; + + // small scale velocity contributions (subscale tracking) + array_1d OldUssTerm = (density/dt) * mOldSubscaleVelocity[rData.IntegrationPointIndex]; // rho * u_ss^{n-1}/dt + + const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); + double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); + + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; + + // Note: Dof order is (vx,vy,[vz,]p) for each node + for (unsigned int i = 0; i < NumNodes; i++) + { + unsigned int row = i*BlockSize; + // Loop over columns + for (unsigned int j = 0; j < NumNodes; j++) + { + unsigned int col = j*BlockSize; + + for (unsigned int d = 0; d < Dim; d++) // iterate over dimensions for velocity Dofs in this node combination + { + double RSigmaG = 0.0; + double GAlphaR = 0.0; + for (unsigned int e = 0; e < Dim; e++){ + double ASigma = tau_one(d,d) * AGradN[i] * sigma(d,e) * rData.N[j]; + double RRSigma = 0.0; + double RSigmaA = tau_one(d,d) * sigma(d,e) * rData.N[i] * AGradN[j]; + double VSigma = tau_one(d,d) * density/dt * rData.N[i] * rData.N[j] * sigma(d,e); + double LSigma_1 = 0.0; + double LSigma_2 = 0.0; + double CSigma = 0.0; + double RSigmaL_1 = 0.0; + double RSigmaL_2 = 0.0; + double RSigmaC = 0.0; + GAlphaR += tau_one(d,d) * fluid_fraction * rData.DN_DX(i,e) * sigma(e,d) * rData.N[j]; + RSigmaG += tau_one(d,d) * sigma(d,e) * rData.N[i] * rData.DN_DX(j,e); + for (unsigned int f = 0; f < Dim; f++){ + LSigma_1 += tau_one(d,d) * viscosity * rData.DDN_DDX[i](f,f) * sigma(d,e) * rData.N[j]; + LSigma_2 += tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,f) * sigma(f,e) * rData.N[j]; + CSigma += 2.0/3.0 * tau_one(d,d) * viscosity * rData.DDN_DDX[i](f,d) * sigma(f,e) * rData.N[j]; + RRSigma += tau_one(d,d) * sigma(d,f) * rData.N[i] * sigma(f,e) * rData.N[j]; + RSigmaL_1 += tau_one(d,d) * viscosity * rData.N[i] * sigma(d,e) * rData.DDN_DDX[j](f,f); + RSigmaL_2 += tau_one(d,d) * viscosity * rData.N[i] * sigma(d,f) * rData.DDN_DDX[j](e,f); + RSigmaC += 2.0/3.0 * tau_one(d,d) * viscosity * sigma(d,f) * rData.N[i] * rData.DDN_DDX[j](f,e); + } + double LSigma = LSigma_1 + LSigma_2; + double RSigmaL = RSigmaL_1 + RSigmaL_2; + rLHS(row+d,col+e) += rData.Weight * (ASigma - RRSigma - RSigmaA - CSigma + LSigma - RSigmaL + RSigmaC - VSigma); + } + rLHS(row+Dim,col+d) += rData.Weight * (GAlphaR); + rLHS(row+d,col+Dim) += rData.Weight * (-RSigmaG); + } + } + + // RHS terms + for (unsigned int d = 0; d < Dim; ++d) + { + double RSigmaF = 0.0; + for (unsigned int e = 0; e < Dim; ++e){ + RSigmaF += tau_one(d,d) * rData.N[i] * sigma(d,e) * (body_force[e] + OldUssTerm[e]); /*- momentum_projection[e]*/ //momentum_projection 0 because is ASGS + } + rLocalRHS[row+d] += rData.Weight * (- RSigmaF); + } + } +} + + template< class TElementData > void DVMSDEMCoupled::AddVelocitySystem( TElementData& rData, MatrixType &rLocalLHS, VectorType &rLocalRHS) { - auto& LHS = rData.LHS; + BoundedMatrix& LHS = rData.LHS; LHS.clear(); const double density = this->GetAtCoordinate(rData.Density,rData.N); const array_1d body_force = density * this->GetAtCoordinate(rData.BodyForce,rData.N); - const array_1d convective_velocity = this->FullConvectiveVelocity(rData); array_1d velocity = this->GetAtCoordinate(rData.Velocity,rData.N); @@ -320,83 +584,114 @@ void DVMSDEMCoupled::AddVelocitySystem( const double fluid_fraction_rate = this->GetAtCoordinate(rData.FluidFractionRate, rData.N); const double mass_source = this->GetAtCoordinate(rData.MassSource, rData.N); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); - array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; - sigma *= viscosity; // Multiplying convective operator by density to have correct units AGradN *= density; // Multiplying convective operator by density to have correct units // Note: Dof order is (u,v,[w,]p) for each node - for (unsigned int i = 0; i < NumNodes; i++) { + for (unsigned int i = 0; i < NumNodes; i++) + { unsigned int row = i*BlockSize; - double divergence_convective = 0.0; - for (unsigned int d = 0; d < Dim; d++) { - divergence_convective += (rData.Velocity(i,d) - rData.MeshVelocity(i,d)) * rData.DN_DX(i,d); - } - // LHS terms - for (unsigned int j = 0; j < NumNodes; j++) { + for (unsigned int j = 0; j < NumNodes; j++) + { unsigned int col = j*BlockSize; // Some terms are the same for all velocity components, calculate them once for each i,j - - // Skew-symmetric convective term 1/2( v*grad(u)*u - grad(v) uu ) - //double K = 0.5*(rN[i]*AGradN[j] - AGradN[i]*rN[j]); double V = rData.N[i]*AGradN[j]; // q-p stabilization block (reset result) double G = 0; - for (unsigned int d = 0; d < Dim; d++) { - // Stabilization: u*grad(v) * TauOne * u*grad(u) - vh * TauOne/Dt u*grad(u) + for (unsigned int d = 0; d < Dim; d++) + { + double AA = tau_one(d,d) * AGradN[i] * AGradN[j];// Stabilization: u*grad(v) * TauOne * u*grad(u) - vh * TauOne/Dt u*grad(u) // The last term comes from vh*d(u_ss)/dt - double AA = AGradN[i] * tau_one(d,d) * AGradN[j]; - double A = tau_one(d,d) * density * rData.N[i]/dt * AGradN[j]; - - LHS(row+d,col+d) += rData.Weight * (V + AA - A); // Galerkin pressure term: Div(v) * p double P = rData.DN_DX(i,d) * rData.N[j]; - - double QD = fluid_fraction * rData.DN_DX(j,d) * rData.N[i]; - + double QD = fluid_fraction * rData.N[i] * rData.DN_DX(j,d); double U = fluid_fraction_gradient[d] * rData.N[j] * rData.N[i]; - - /* q-p stabilization block */ - // Stabilization: Grad(q) * TauOne * Grad(p) - G += tau_one(d,d) * fluid_fraction * rData.DN_DX(i,d) * rData.DN_DX(j,d); /* v-u block */ // Stabilization: Div(v) * TauTwo * Div(u) - double GAlphaR = 0.0; - double RSigmaG = 0.0; - double GAlphaA = tau_one(d,d) * AGradN[j] * fluid_fraction * rData.DN_DX(i,d); + + double GAlphaA = tau_one(d,d) * fluid_fraction * rData.DN_DX(i,d) * AGradN[j]; + double GAlphaL_1 = 0.0; + double GAlphaL_2 = 0.0; + double GAlphaC = 0.0; // Stabilization: (a * Grad(v)) * TauOne * Grad(p) double AG = tau_one(d,d) * AGradN[i] * rData.DN_DX(j,d); + double LG_1 = 0.0; + double LG_2 = 0.0; + double CG = 0.0; // From vh*d(u_ss)/dt: vh * TauOne/Dt * Grad(p) double VP = tau_one(d,d) * density * rData.N[i] / dt * rData.DN_DX(j,d); + /* q-p stabilization block */ + // Stabilization: Grad(q) * TauOne * Grad(p) + G += tau_one(d,d) * fluid_fraction * rData.DN_DX(i,d) * rData.DN_DX(j,d); for (unsigned int e = 0; e < Dim; e++){ + double DnuD = 2.0/3.0 * viscosity * rData.DN_DX(i,d) * rData.DN_DX(j,e); + double GS = viscosity * rData.DN_DX(i,e) * rData.DN_DX(j,d); + double L = tau_one(d,d) * viscosity * density/dt * rData.N[i] * rData.DDN_DDX[j](d,e); + double C = 2.0/3.0 * tau_one(d,d) * viscosity * density/dt * rData.N[i] * rData.DDN_DDX[j](d,e); + double DU = tau_two * rData.DN_DX(i,d) * fluid_fraction_gradient[e] * rData.N[j]; + double DD = tau_two * fluid_fraction * rData.DN_DX(i,d) * rData.DN_DX(j,e); double RSigma = rData.N[i] * sigma(d,e) * rData.N[j]; - double VSigma = tau_one(d,d) * density/dt * rData.N[i] * rData.N[j] * sigma(d,e); - double ASigma = tau_one(d,d) * AGradN[i] * sigma(d,e) * rData.N[j]; - double RRSigma = tau_one(d,d) * sigma(d,e) * rData.N[i] * sigma(e,d) * rData.N[j]; - double RSigmaA = tau_one(d,d) * sigma(d,e) * rData.N[i] * AGradN[j]; - double DD = fluid_fraction * tau_two * rData.DN_DX(i,d) * rData.DN_DX(j,e); - double DU = fluid_fraction_gradient[e] * tau_two * rData.DN_DX(i,d) * rData.N[j]; - GAlphaR += tau_one(d,d) * fluid_fraction * rData.DN_DX(i,d) * sigma(d,e) * rData.N[j]; - RSigmaG += tau_one(d,d) * sigma(d,e) * rData.N[i] * rData.DN_DX(j,e); - LHS(row+d,col+e) += rData.Weight * (DD + DU + RSigma - VSigma + ASigma - RRSigma - RSigmaA); - } + double AL = tau_one(d,d) * viscosity * AGradN[i] * rData.DDN_DDX[j](d,e); + double AC = 2.0 / 3.0 * tau_one(d,d) * viscosity * AGradN[i] * rData.DDN_DDX[j](d,e); + double LA = tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,e) * AGradN[j]; + double LL_diag_1 = 0.0; + double LL_diag_2 = 0.0; + double LL_2 = 0.0; + double LL_3 = 0.0; + double LL_4 = 0.0; + double LC_1 = 0.0; + double LC_2 = 0.0; + double CA = 2.0/3.0 * tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,e) * AGradN[j]; + double CL_1 = 0.0; + double CL_2 = 0.0; + double CC = 0.0; + GAlphaL_1 += tau_one(d,d) * viscosity * fluid_fraction * rData.DN_DX(i,d) * rData.DDN_DDX[j](e,e); + GAlphaL_2 += tau_one(d,d) * viscosity * fluid_fraction * rData.DN_DX(i,e) * rData.DDN_DDX[j](d,e); + GAlphaC += 2.0/3.0 * tau_one(d,d) * viscosity * fluid_fraction * rData.DN_DX(i,e) * rData.DDN_DDX[j](e,d); + LG_1 += tau_one(d,d) * viscosity * rData.DDN_DDX[i](e,e) * rData.DN_DX(j,d); + LG_2 += tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,e) * rData.DN_DX(j,e); + CG += 2.0/3.0 * tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,e) * rData.DN_DX(j,e); + for (unsigned int f = 0; f < Dim; f++){ + if (d == e){ + GS += viscosity * rData.DN_DX(i,f) * rData.DN_DX(j,f); + AL += tau_one(d,d) * viscosity * AGradN[i] * rData.DDN_DDX[j](f,f); + LA += tau_one(d,d) * viscosity * rData.DDN_DDX[i](f,f) * AGradN[j]; + LL_diag_1 += tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](f,f); + LL_diag_2 += rData.DDN_DDX[j](f,f); + L += tau_one(d,d) * viscosity * density/dt * rData.N[i] * rData.DDN_DDX[j](f,f); + } + LL_2 += tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](f,f) * rData.DDN_DDX[j](d,e); + LL_3 += tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](d,e) * rData.DDN_DDX[j](f,f); + LL_4 += tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](d,f) * rData.DDN_DDX[j](e,f); + LC_1 += 2.0/3.0 * tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](f,f) * rData.DDN_DDX[j](d,e); + LC_2 += 2.0/3.0 * tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](d,f) * rData.DDN_DDX[j](f,e); + CL_1 += 2.0 / 3.0 * tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](d,e) * rData.DDN_DDX[j](f,f); + CL_2 += 2.0/3.0 * tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](d,f) * rData.DDN_DDX[j](f,e); + CC += 4.0/9.0 * tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](f,d) * rData.DDN_DDX[j](f,e); + } + double LL = (LL_diag_1 * LL_diag_2) + LL_2 + LL_3 + LL_4; + double LC = LC_1 + LC_2; + double CL = CL_1 + CL_2; + LHS(row+d,col+e) += rData.Weight * (L - C + GS - DnuD - AL + AC + LA - LL + LC - CA + CL - CC + DD + DU + RSigma); - LHS(row+Dim,col+d) += rData.Weight * (GAlphaA + U + QD + GAlphaR); - LHS(row+d,col+Dim) += rData.Weight * (AG - VP - P - RSigmaG); + } + double GAlphaL = GAlphaL_1 + GAlphaL_2; + double LG = LG_1 + LG_2; + LHS(row+d,col+d) += rData.Weight * (V + AA - A); + LHS(row+Dim,col+d) += rData.Weight * (GAlphaA + U + QD - GAlphaL + GAlphaC); + LHS(row+d,col+Dim) += rData.Weight * (AG - VP - P + LG - CG); } // Write q-p term @@ -405,6 +700,7 @@ void DVMSDEMCoupled::AddVelocitySystem( // RHS terms double QAlphaF = 0.0; + double Q = rData.N[i] * (mass_source - fluid_fraction_rate); for (unsigned int d = 0; d < Dim; ++d) { // v*BodyForce + v * du_ss/dt @@ -413,20 +709,28 @@ void DVMSDEMCoupled::AddVelocitySystem( // vh * TauOne/Dt * f (from vh*d(uss)/dt double VI = tau_one(d,d) * density * rData.N[i] / dt * (body_force[d] - MomentumProj[d] + OldUssTerm[d]); double AF = tau_one(d,d) * AGradN[i] * (body_force[d] - MomentumProj[d] + OldUssTerm[d]); - double RSigmaF = 0.0; + double LF_1 = 0.0; + double LF_2 = 0.0; + double CF = 0.0; + // Grad(q) * TauOne * (Density * BodyForce - Projection) + QAlphaF += tau_one(d,d) * fluid_fraction * rData.DN_DX(i,d) * (body_force[d] - MomentumProj[d] + OldUssTerm[d]); for (unsigned int e = 0; e < Dim; ++e){ - RSigmaF += tau_one(d,d) * sigma(d,e) * rData.N[i] * (body_force[e] - MomentumProj[e] + OldUssTerm[e]); + LF_1 += tau_one(d,d) * viscosity * rData.DDN_DDX[i](e,e) * (body_force[d] - MomentumProj[d] + OldUssTerm[d]); + LF_2 += tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,e) * (body_force[e] - MomentumProj[e] + OldUssTerm[e]); + CF += 2.0/3.0 * tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,e) * (body_force[e] - MomentumProj[e] + OldUssTerm[e]); } - // Grad(q) * TauOne * (Density * BodyForce - Projection) - QAlphaF += tau_one(d,d) * rData.DN_DX(i,d) * fluid_fraction * (body_force[d] - MomentumProj[d] + OldUssTerm[d]); + double LF = LF_1 + LF_2; // OSS pressure subscale projection - double DPhi = rData.DN_DX(i,d) * tau_two * (mass_source - fluid_fraction_rate - MassProj); - rLocalRHS[row+d] += rData.Weight * (VF - VI + AF + DPhi - RSigmaF); + double DPhi = tau_two * rData.DN_DX(i,d) * (mass_source - fluid_fraction_rate - MassProj); + rLocalRHS[row+d] += rData.Weight * (VF - VI + AF + LF - CF + DPhi); } - double Q = rData.N[i] * (mass_source - fluid_fraction_rate); rLocalRHS[row+Dim] += rData.Weight * (QAlphaF + Q); // Grad(q) * TauOne * (Density * BodyForce) } + // Adding reactive terms to the stabilization + if(!rData.UseOSS) + this->AddReactionStabilization(rData,LHS,rLocalRHS); + // Write (the linearized part of the) local contribution into residual form (A*dx = b - A*x) array_1d values; this->GetCurrentValuesVector(rData,values); @@ -436,11 +740,131 @@ void DVMSDEMCoupled::AddVelocitySystem( * For a generic (potentially non-linear) constitutive law, one cannot assume that RHS = F - LHS*current_values. * Because of this, the AddViscousTerm function manages both the LHS and the RHS. */ - this->AddViscousTerm(rData,LHS,rLocalRHS); + //this->AddViscousTerm(rData,LHS,rLocalRHS); noalias(rLocalLHS) += LHS; } +template +void DVMSDEMCoupled::CalculateMassMatrix(MatrixType& rMassMatrix, + const ProcessInfo& rCurrentProcessInfo) +{ + // Resize and intialize output + if (rMassMatrix.size1() != LocalSize) + rMassMatrix.resize(LocalSize, LocalSize, false); + + noalias(rMassMatrix) = ZeroMatrix(LocalSize, LocalSize); + + if (!TElementData::ElementManagesTimeIntegration) { + // Get Shape function data + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + DenseVector> shape_function_second_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); + const unsigned int number_of_gauss_points = gauss_weights.size(); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + // Iterate over integration points to evaluate local contribution + for (unsigned int g = 0; g < number_of_gauss_points; g++) { + this->UpdateIntegrationPointDataSecondDerivatives( + data, g, gauss_weights[g], + row(shape_functions, g),shape_derivatives[g],shape_function_second_derivatives[g]); + + this->AddMassLHS(data, rMassMatrix); + } + } +} + +template +void DVMSDEMCoupled::CalculateLocalVelocityContribution(MatrixType& rDampMatrix, + VectorType& rRightHandSideVector, + const ProcessInfo& rCurrentProcessInfo) +{ + // Resize and intialize output + if( rDampMatrix.size1() != LocalSize ) + rDampMatrix.resize(LocalSize,LocalSize,false); + + if( rRightHandSideVector.size() != LocalSize ) + rRightHandSideVector.resize(LocalSize,false); + + noalias(rDampMatrix) = ZeroMatrix(LocalSize,LocalSize); + noalias(rRightHandSideVector) = ZeroVector(LocalSize); + + if (!TElementData::ElementManagesTimeIntegration) { + // Get Shape function data + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + DenseVector> shape_function_second_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + const unsigned int number_of_gauss_points = gauss_weights.size(); + + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + // Iterate over integration points to evaluate local contribution + for (unsigned int g = 0; g < number_of_gauss_points; g++) { + const auto& r_dndx = shape_derivatives[g]; + this->UpdateIntegrationPointDataSecondDerivatives( + data, g, gauss_weights[g], + row(shape_functions, g),r_dndx, shape_function_second_derivatives[g]); + + this->AddVelocitySystem(data, rDampMatrix, rRightHandSideVector); + } + } +} + +template < class TElementData > +void DVMSDEMCoupled::CalculateResistanceTensor( + const TElementData& rData) +{ + BoundedMatrix& rsigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; + BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); + + rsigma = permeability; +} + +template< class TElementData > +void DVMSDEMCoupled::AddMassLHS( + TElementData& rData, + MatrixType &rMassMatrix) +{ + const double density = this->GetAtCoordinate(rData.Density,rData.N); + // Note: Dof order is (u,v,[w,]p) for each node + for (unsigned int i = 0; i < NumNodes; i++) + { + unsigned int row = i*BlockSize; + for (unsigned int j = 0; j < NumNodes; j++) + { + unsigned int col = j*BlockSize; + const double Mij = rData.Weight * density * rData.N[i] * rData.N[j]; + for (unsigned int d = 0; d < Dim; d++) + rMassMatrix(row+d,col+d) += Mij; + } + } + + /* Note on OSS and full projection: Riccardo says that adding the terms provided by + * AddMassStabilization (and incluiding their corresponding terms in the projeciton) + * could help reduce the non-linearity of the coupling between projection and u,p + * However, leaving them on gives a lot of trouble whith the Bossak scheme: + * think that we solve F - (1-alpha)*M*u^(n+1) - alpha*M*u^(n) - K(u^(n+1)) = 0 + * so the projection of the dynamic terms should be Pi( (1-alpha)*u^(n+1) - alpha*u^(n) ) + */ + if (!rData.UseOSS) + this->AddMassStabilization(rData,rMassMatrix); +} + + template void DVMSDEMCoupled::MassProjTerm( const TElementData& rData, @@ -449,7 +873,7 @@ void DVMSDEMCoupled::MassProjTerm( const auto velocities = rData.Velocity; const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); - const auto fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); const double mass_source = this->GetAtCoordinate(rData.MassSource, rData.N); const double fluid_fraction_rate = this->GetAtCoordinate(rData.FluidFractionRate, rData.N); @@ -457,7 +881,7 @@ void DVMSDEMCoupled::MassProjTerm( for (unsigned int i = 0; i < NumNodes; i++) { for (unsigned int d = 0; d < Dim; ++d) { - rMassRHS -= (fluid_fraction * rData.DN_DX(i, d) * velocities(i, d)) + fluid_fraction_gradient[d] * rData.N[i] * velocities(i, d); + rMassRHS -= (fluid_fraction * rData.DN_DX(i, d) * velocities(i, d) + fluid_fraction_gradient[d] * rData.N[i] * velocities(i, d)); } } rMassRHS += mass_source - fluid_fraction_rate; @@ -487,24 +911,15 @@ void DVMSDEMCoupled::AddMassStabilization( const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; - double W = rData.Weight * density; // This density is for the dynamic term in the residual (rho*Du/Dt) - sigma *= viscosity; + const double weight = rData.Weight * density; // This density is for the dynamic term in the residual (rho*Du/Dt) // Note: Dof order is (u,v,[w,]p) for each node for (unsigned int i = 0; i < NumNodes; i++) { unsigned int row = i*BlockSize; - double divergence_convective = 0.0; - for (unsigned int d = 0; d < Dim; d++) { - divergence_convective += (rData.Velocity(i,d) - rData.MeshVelocity(i,d)) * rData.DN_DX(i,d); - } - for (unsigned int j = 0; j < NumNodes; j++) { unsigned int col = j*BlockSize; @@ -517,11 +932,16 @@ void DVMSDEMCoupled::AddMassStabilization( double AU = tau_one(d,d) * AGradN[i] * rData.N[j]; double IU = tau_one(d,d) * rData.N[i]/dt * rData.N[j]; for (unsigned int e = 0; e < Dim; ++e){ + double LI = tau_one(d,d) * viscosity * rData.N[j] * rData.DDN_DDX[i](d,e); + double CI = 2.0/3.0 * tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,e) * rData.N[j]; double RSigmaU = tau_one(d,d) * sigma(d,e) * rData.N[i] * rData.N[j]; - rMassMatrix(row+d, col+e) -= W * RSigmaU; + for (unsigned int f = 0; f < Dim; f++) + if (d == e) + LI += tau_one(d,d) * viscosity * rData.DDN_DDX[i](f,f) * rData.N[j]; + rMassMatrix(row+d, col+e) += weight * (LI - CI - RSigmaU); } - rMassMatrix(row+d,col+d) += W * (AU - IU); - rMassMatrix(row+Dim,col+d) += W * UGAlpha; + rMassMatrix(row+d,col+d) += weight * (AU - IU); + rMassMatrix(row+Dim,col+d) += weight * UGAlpha; } } } @@ -536,8 +956,11 @@ void DVMSDEMCoupled::CalculateProjections(const ProcessInfo &rCurr Vector gauss_weights; Matrix shape_functions; ShapeFunctionDerivativesArrayType shape_function_derivatives; + DenseVector> shape_function_second_derivatives; this->CalculateGeometryData(gauss_weights,shape_functions,shape_function_derivatives); const unsigned int NumGauss = gauss_weights.size(); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); VectorType MomentumRHS = ZeroVector(NumNodes * Dim); VectorType MassRHS = ZeroVector(NumNodes); @@ -548,9 +971,9 @@ void DVMSDEMCoupled::CalculateProjections(const ProcessInfo &rCurr for (unsigned int g = 0; g < NumGauss; g++) { - this->UpdateIntegrationPointData( + this->UpdateIntegrationPointDataSecondDerivatives( data, g, gauss_weights[g], - row(shape_functions,g),shape_function_derivatives[g]); + row(shape_functions,g),shape_function_derivatives[g],shape_function_second_derivatives[g]); array_1d MomentumRes = ZeroVector(3); double MassRes = 0.0; @@ -593,40 +1016,42 @@ void DVMSDEMCoupled::CalculateStabilizationParameters( BoundedMatrix &TauOne, double &TauTwo) const { - double tau_one; - double inv_tau; - double tau_one_NS; - double inv_tau_NS; const double h = rData.ElementSize; const double density = this->GetAtCoordinate(rData.Density,rData.N); const double viscosity = this->GetAtCoordinate(rData.EffectiveViscosity,rData.N); - double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); - constexpr double c1 = DVMS::mTauC1; - constexpr double c2 = DVMS::mTauC2; - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); + const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); + constexpr double c1 = 8.0; + constexpr double c2 = 2.0; + const int p = mInterpolationOrder; + + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; + BoundedMatrix I = IdentityMatrix(Dim, Dim); + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); + // This last term does not exist physically and it is included to do the spectral radius taking into account the inverse Gamma + // whose size is (d+1,d+1) - double velocity_norm = 0.0; - double sigma_term = 0.0; + double velocity_modulus = 0.0; + double fluid_fraction_gradient_modulus = 0.0; for (unsigned int d = 0; d < Dim; d++){ - velocity_norm += Velocity[d] * Velocity[d]; - for (unsigned int e = d; e < Dim; e++){ - sigma_term += std::pow(sigma(d,e),2); - } + velocity_modulus += Velocity[d] * Velocity[d]; + fluid_fraction_gradient_modulus += std::pow(fluid_fraction_gradient[d],2); } - velocity_norm = std::sqrt(velocity_norm); + double velocity_norm = std::sqrt(velocity_modulus); + double fluid_fraction_gradient_norm = std::sqrt(fluid_fraction_gradient_modulus); + + double c_alpha = 1.0 + h / c1 * fluid_fraction_gradient_norm; + + double inv_tau_NS = c1 * viscosity / std::pow(h/(p*p),2.0) + density * (c2 * velocity_norm / (h/p) ); + double tau_one_NS = 1.0 / inv_tau_NS; + + double inv_tau = (c1 * viscosity / std::pow(h/(p*p),2.0) + density * (c2 * velocity_norm / (h/p) ) ) * c_alpha + density / rData.DeltaTime; + double tau_one = 1.0 / (inv_tau + sigma(0,0)); - inv_tau = c1 * viscosity / (h * h) + density * ( 1.0 / rData.DeltaTime + c2 * velocity_norm / h ) + viscosity * std::sqrt(sigma_term); - inv_tau_NS = c1 * viscosity / (h * h) + density * ( c2 * velocity_norm / h ) + viscosity * std::sqrt(sigma_term); - tau_one = 1 / inv_tau; - tau_one_NS = 1 / inv_tau_NS; TauOne = tau_one * I; - TauTwo = h * h / (c1 * fluid_fraction * tau_one_NS); + TauTwo = std::pow(h/p,2.0) / (c1 * fluid_fraction * tau_one_NS); } template< class TElementData > @@ -700,26 +1125,17 @@ void DVMSDEMCoupled::UpdateSubscaleVelocity( const TElementData& rData) { const double density = this->GetAtCoordinate(rData.Density,rData.N); - double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction,rData.N); + array_1d predicted_subscale_velocity = ZeroVector(3); const array_1d& r_old_subscale_velocity = mOldSubscaleVelocity[rData.IntegrationPointIndex]; - - array_1d previous_subscale_velocity = ZeroVector(3); - array_1d previous_velocity = mPreviousVelocity[rData.IntegrationPointIndex]; - - for (size_t i = 0; i < NumNodes; i++) { - array_1d subscale_velocity_on_previous_iteration = mPredictedSubscaleVelocity[rData.IntegrationPointIndex]; - for (size_t d = 0; d < Dim; d++) { - previous_subscale_velocity[d] += subscale_velocity_on_previous_iteration[d]; - } - } + array_1d subscale_velocity_on_previous_iteration = mPredictedSubscaleVelocity[rData.IntegrationPointIndex]; array_1d v_d = ZeroVector(Dim); + for (unsigned int d = 0; d < Dim; d++) - { - v_d[d] = previous_velocity[d] + previous_subscale_velocity[d]; - } + v_d[d] = previous_velocity[d] + subscale_velocity_on_previous_iteration[d]; + const double dt = rData.DeltaTime; // Part of the residual that does not depend on the subscale @@ -737,9 +1153,8 @@ void DVMSDEMCoupled::UpdateSubscaleVelocity( this->CalculateStabilizationParameters(rData,v_d,tau_one,tau_two); for (unsigned int d = 0; d < Dim; d++) - { - predicted_subscale_velocity[d] = tau_one(d,d) * (static_residual[d] + fluid_fraction * (density/dt)*r_old_subscale_velocity[d]); - } + predicted_subscale_velocity[d] = tau_one(d,d) * (static_residual[d] + (density/dt)*r_old_subscale_velocity[d]); + noalias(mPredictedSubscaleVelocity[rData.IntegrationPointIndex]) = predicted_subscale_velocity; } @@ -895,6 +1310,9 @@ template class DVMSDEMCoupled< QSVMSDEMCoupledData<2,3> >; template class DVMSDEMCoupled< QSVMSDEMCoupledData<3,4> >; template class DVMSDEMCoupled< QSVMSDEMCoupledData<2,4> >; +template class DVMSDEMCoupled< QSVMSDEMCoupledData<2,6> >; +template class DVMSDEMCoupled< QSVMSDEMCoupledData<2,9> >; template class DVMSDEMCoupled< QSVMSDEMCoupledData<3,8> >; +template class DVMSDEMCoupled< QSVMSDEMCoupledData<3,27> >; -} // namespace Kratos +} // namespace Kratos \ No newline at end of file diff --git a/applications/FluidDynamicsApplication/custom_elements/d_vms_dem_coupled.h b/applications/FluidDynamicsApplication/custom_elements/d_vms_dem_coupled.h index 41407ed53dfb..46f51421ce3d 100644 --- a/applications/FluidDynamicsApplication/custom_elements/d_vms_dem_coupled.h +++ b/applications/FluidDynamicsApplication/custom_elements/d_vms_dem_coupled.h @@ -92,6 +92,8 @@ class DVMSDEMCoupled : public DVMS /// Type for an array of shape function gradient matrices typedef GeometryType::ShapeFunctionsGradientsType ShapeFunctionDerivativesArrayType; + typedef GeometryType::ShapeFunctionsSecondDerivativesType ShapeFunctionsSecondDerivativesType; + constexpr static unsigned int Dim = DVMS::Dim; constexpr static unsigned int NumNodes = DVMS::NumNodes; constexpr static unsigned int BlockSize = DVMS::BlockSize; @@ -173,6 +175,23 @@ class DVMSDEMCoupled : public DVMS void Initialize(const ProcessInfo& rCurrentProcessInfo) override; + GeometryData::IntegrationMethod GetIntegrationMethod() const override; + + void CalculateOnIntegrationPoints( + const Variable>& rVariable, + std::vector>& rOutput, + const ProcessInfo& rCurrentProcessInfo) override; + + void CalculateOnIntegrationPoints( + const Variable& rVariable, + std::vector& rOutput, + const ProcessInfo& rCurrentProcessInfo) override; + + void CalculateOnIntegrationPoints( + Variable const& rVariable, + std::vector& rValues, + ProcessInfo const& rCurrentProcessInfo) override; + void FinalizeSolutionStep(const ProcessInfo& rCurrentProcessInfo) override; void InitializeNonLinearIteration(const ProcessInfo& rCurrentProcessInfo) override; @@ -210,7 +229,8 @@ class DVMSDEMCoupled : public DVMS ///@} ///@name Protected member Variables ///@{ - + int mInterpolationOrder = 1; + DenseVector > mViscousResistanceTensor; // Velocity subscale history, stored at integration points DenseVector< array_1d > mPredictedSubscaleVelocity; DenseVector< array_1d > mOldSubscaleVelocity; @@ -242,7 +262,10 @@ class DVMSDEMCoupled : public DVMS MatrixType& rLocalLHS, VectorType& rLocalRHS) override; - // Implementation details of DVMSDEMCoupled ///////////////////////////////////////// + void AddReactionStabilization( + TElementData& rData, + BoundedMatrix& rLHS, + VectorType& rLocalRHS); void AddMassStabilization( TElementData& rData, @@ -256,6 +279,14 @@ class DVMSDEMCoupled : public DVMS BoundedMatrix &TauOne, double &TauTwo) const; + void UpdateIntegrationPointDataSecondDerivatives( + TElementData& rData, + unsigned int IntegrationPointIndex, + double Weight, + const typename TElementData::MatrixRowType& rN, + const typename TElementData::ShapeDerivativesType& rDN_DX, + const typename TElementData::ShapeFunctionsSecondDerivativesType& rDDN_DDX) const; + void SubscaleVelocity( const TElementData& rData, array_1d& rVelocitySubscale) const override; @@ -264,6 +295,13 @@ class DVMSDEMCoupled : public DVMS const TElementData& rData, double& rPressureSubscale) const override; + void CalculateMassMatrix(MatrixType& rMassMatrix, + const ProcessInfo& rCurrentProcessInfo) override; + + void CalculateLocalVelocityContribution(MatrixType& rDampMatrix, + VectorType& rRightHandSideVector, + const ProcessInfo& rCurrentProcessInfo) override; + array_1d FullConvectiveVelocity( const TElementData& rData) const override; @@ -273,6 +311,13 @@ class DVMSDEMCoupled : public DVMS void UpdateSubscaleVelocity( const TElementData& rData); + void CalculateResistanceTensor( + const TElementData& rData); + + void AddMassLHS( + TElementData& rData, + MatrixType& rMassMatrix) override; + void MassProjTerm( const TElementData& rData, double& rMassRHS) const override; diff --git a/applications/FluidDynamicsApplication/custom_elements/fluid_element.cpp b/applications/FluidDynamicsApplication/custom_elements/fluid_element.cpp index 59187aaf91e8..8204a2c31a1e 100644 --- a/applications/FluidDynamicsApplication/custom_elements/fluid_element.cpp +++ b/applications/FluidDynamicsApplication/custom_elements/fluid_element.cpp @@ -929,7 +929,10 @@ template class FluidElement< QSVMSDEMCoupledData<2,3> >; template class FluidElement< QSVMSDEMCoupledData<3,4> >; template class FluidElement< QSVMSDEMCoupledData<2,4> >; +template class FluidElement< QSVMSDEMCoupledData<2,6> >; +template class FluidElement< QSVMSDEMCoupledData<2,9> >; template class FluidElement< QSVMSDEMCoupledData<3,8> >; +template class FluidElement< QSVMSDEMCoupledData<3,27> >; template class FluidElement< FICData<2,3> >; template class FluidElement< FICData<3,4> >; diff --git a/applications/FluidDynamicsApplication/custom_elements/qs_vms.cpp b/applications/FluidDynamicsApplication/custom_elements/qs_vms.cpp index 5515bc900712..228f179dda98 100644 --- a/applications/FluidDynamicsApplication/custom_elements/qs_vms.cpp +++ b/applications/FluidDynamicsApplication/custom_elements/qs_vms.cpp @@ -836,9 +836,12 @@ template class QSVMS< TimeIntegratedQSVMSData<2,3> >; template class QSVMS< TimeIntegratedQSVMSData<3,4> >; template class QSVMS< QSVMSDEMCoupledData<2,3> >; +template class QSVMS< QSVMSDEMCoupledData<2,6> >; template class QSVMS< QSVMSDEMCoupledData<3,4> >; template class QSVMS< QSVMSDEMCoupledData<2,4> >; +template class QSVMS< QSVMSDEMCoupledData<2,9> >; template class QSVMS< QSVMSDEMCoupledData<3,8> >; +template class QSVMS< QSVMSDEMCoupledData<3,27> >; } // namespace Kratos diff --git a/applications/FluidDynamicsApplication/custom_elements/qs_vms_dem_coupled.cpp b/applications/FluidDynamicsApplication/custom_elements/qs_vms_dem_coupled.cpp index ce8e34cfe4ed..51431713f28c 100644 --- a/applications/FluidDynamicsApplication/custom_elements/qs_vms_dem_coupled.cpp +++ b/applications/FluidDynamicsApplication/custom_elements/qs_vms_dem_coupled.cpp @@ -66,6 +66,172 @@ Element::Pointer QSVMSDEMCoupled::Create(IndexType NewId,GeometryT return Kratos::make_intrusive(NewId, pGeom, pProperties); } +template< class TElementData > +void QSVMSDEMCoupled::CalculateOnIntegrationPoints( + const Variable& rVariable, + std::vector& rOutput, + const ProcessInfo& rCurrentProcessInfo) +{ + const GeometryType::IntegrationPointsArrayType integration_points = this->GetGeometry().IntegrationPoints(this->GetIntegrationMethod()); + const SizeType number_of_integration_points = integration_points.size(); + + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + + if (rOutput.size() != number_of_integration_points) + rOutput.resize(number_of_integration_points); + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + for (unsigned int g = 0; g < number_of_integration_points; g++ ) { + data.UpdateGeometryValues(g, gauss_weights[g], row(shape_functions, g),shape_derivatives[g]); + if (rVariable == PRESSURE) { + const auto& r_pressure = data.Pressure; + double value = this->GetAtCoordinate(r_pressure,data.N); + rOutput[g] = value; + } + } +} + +template< class TElementData > +void QSVMSDEMCoupled::CalculateOnIntegrationPoints( + const Variable& rVariable, + std::vector& rValues, + const ProcessInfo& rCurrentProcessInfo) +{ + const GeometryType::IntegrationPointsArrayType integration_points = this->GetGeometry().IntegrationPoints(this->GetIntegrationMethod()); + const SizeType number_of_integration_points = integration_points.size(); + + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + + if (rValues.size() != number_of_integration_points) + rValues.resize(number_of_integration_points); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + for (unsigned int g = 0; g < number_of_integration_points; g++ ) { + data.UpdateGeometryValues(g, gauss_weights[g], row(shape_functions, g),shape_derivatives[g]); + Matrix value = ZeroMatrix(Dim, Dim); + if (rVariable == VELOCITY_GRADIENT) { + const auto& r_velocity = data.Velocity; + for (unsigned int i = 0; i < NumNodes; i++) { + for (unsigned int d = 0; d < Dim; d++) { + for (unsigned int e = 0; e < Dim; e++) + value(d,e) += data.DN_DX(i,d) * r_velocity(i,e); + } + } + } + rValues[g] = value; + } +} + +template< class TElementData > +void QSVMSDEMCoupled::CalculateOnIntegrationPoints( + const Variable>& rVariable, + std::vector>& rOutput, + const ProcessInfo& rCurrentProcessInfo) +{ + const GeometryType::IntegrationPointsArrayType integration_points = this->GetGeometry().IntegrationPoints(this->GetIntegrationMethod()); + const SizeType number_of_integration_points = integration_points.size(); + + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + + if (rOutput.size() != number_of_integration_points) + rOutput.resize(number_of_integration_points); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + + for (unsigned int g = 0; g < number_of_integration_points; g++ ) { + data.UpdateGeometryValues(g, gauss_weights[g], row(shape_functions, g),shape_derivatives[g]); + array_1d value(3,0.0); + if (rVariable == VELOCITY) { + const auto& r_velocity = data.Velocity; + value = this->GetAtCoordinate(r_velocity,data.N); + } + if (rVariable == BODY_FORCE) { + value = this->GetAtCoordinate(data.BodyForce,data.N); + } + if (rVariable == PRESSURE_GRADIENT){ + const auto& r_pressure = data.Pressure; + for (unsigned int i = 0; i < NumNodes; i++) { + for (unsigned int d = 0; d < Dim; d++) { + value[d] += r_pressure[i] * data.DN_DX(i,d); + } + } + } + rOutput[g] = value; + } +} + +template +void QSVMSDEMCoupled::Initialize(const ProcessInfo& rCurrentProcessInfo) +{ + // Base class does things with constitutive law here. + QSVMS::Initialize(rCurrentProcessInfo); + + if(Dim == 2){ + if (NumNodes == 9 || NumNodes == 6 || NumNodes == 4) + mInterpolationOrder = 2; + } + else if(Dim == 3){ + if (NumNodes == 10 || NumNodes == 27) + mInterpolationOrder = 2; + } + + const unsigned int number_of_gauss_points = this->GetGeometry().IntegrationPointsNumber(this->GetIntegrationMethod()); + + // The old velocity may be already defined (if restarting) + // and we want to keep the loaded values in that case. + if (mPreviousVelocity.size() != number_of_gauss_points) + { + mPreviousVelocity.resize(number_of_gauss_points); + for (unsigned int g = 0; g < number_of_gauss_points; g++) + mPreviousVelocity[g] = ZeroVector(Dim); + } + + if (mPredictedSubscaleVelocity.size() != number_of_gauss_points) + { + mPredictedSubscaleVelocity.resize(number_of_gauss_points); + for (unsigned int g = 0; g < number_of_gauss_points; g++) + mPredictedSubscaleVelocity[g] = ZeroVector(Dim); + } + // The prediction is updated before each non-linear iteration: + // It is not stored in a restart and can be safely initialized. + + // The old velocity may be already defined (if restarting) + // and we want to keep the loaded values in that case. + if (mViscousResistanceTensor.size() != number_of_gauss_points) + { + mViscousResistanceTensor.resize(number_of_gauss_points); + for (unsigned int g = 0; g < number_of_gauss_points; g++) + mViscousResistanceTensor[g] = ZeroMatrix(Dim,Dim); + } +} + + + +template< class TElementData > +GeometryData::IntegrationMethod QSVMSDEMCoupled::GetIntegrationMethod() const +{ + if(mInterpolationOrder == 1) + return GeometryData::IntegrationMethod::GI_GAUSS_2; + else + return GeometryData::IntegrationMethod::GI_GAUSS_3; +} + /////////////////////////////////////////////////////////////////////////////////////////////////// // Inquiry @@ -133,6 +299,64 @@ void QSVMSDEMCoupled::PrintInfo(std::ostream& rOStream) const rOStream << "QSVMSDEMCoupled" << Dim << "D"; } +template +void QSVMSDEMCoupled::InitializeNonLinearIteration(const ProcessInfo& rCurrentProcessInfo) +{ + // Get Shape function data + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_function_derivatives; + DenseVector> shape_function_second_derivatives; + this->CalculateGeometryData(gauss_weights,shape_functions,shape_function_derivatives); + const unsigned int number_of_integration_points = gauss_weights.size(); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); + TElementData data; + data.Initialize(*this,rCurrentProcessInfo); + + for (unsigned int g = 0; g < number_of_integration_points; g++) { + this->UpdateIntegrationPointDataSecondDerivatives(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g],shape_function_second_derivatives[g]); + + this->CalculateResistanceTensor(data); + //this->UpdateSubscaleVelocity(data); + } +} + +template +void QSVMSDEMCoupled::FinalizeNonLinearIteration(const ProcessInfo& rCurrentProcessInfo) +{ + //Get Shape function data + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_function_derivatives; + DenseVector> shape_function_second_derivatives; + this->CalculateGeometryData(gauss_weights,shape_functions,shape_function_derivatives); + const unsigned int number_of_integration_points = gauss_weights.size(); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); + TElementData data; + data.Initialize(*this,rCurrentProcessInfo); + + for (unsigned int g = 0; g < number_of_integration_points; g++) { + this->UpdateIntegrationPointDataSecondDerivatives(data, g, gauss_weights[g],row(shape_functions,g),shape_function_derivatives[g],shape_function_second_derivatives[g]); + + this->UpdateSubscaleVelocity(data); + } +} + +template +void QSVMSDEMCoupled::UpdateIntegrationPointDataSecondDerivatives( + TElementData& rData, + unsigned int IntegrationPointIndex, + double Weight, + const typename TElementData::MatrixRowType& rN, + const typename TElementData::ShapeDerivativesType& rDN_DX, + const typename TElementData::ShapeFunctionsSecondDerivativesType& rDDN_DDX) const +{ + this->UpdateIntegrationPointData(rData, IntegrationPointIndex, Weight, rN, rDN_DX); + rData.UpdateSecondDerivativesValues(rDDN_DDX); +} + template void QSVMSDEMCoupled::CalculateRightHandSide( VectorType& rRightHandSideVector, @@ -158,25 +382,28 @@ void QSVMSDEMCoupled::AlgebraicMomentumResidual( const double density = this->GetAtCoordinate(rData.Density,rData.N); const double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); const auto& r_body_forces = rData.BodyForce; const auto& r_velocities = rData.Velocity; const auto& r_pressures = rData.Pressure; - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); - sigma *= viscosity; + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; + Vector sigma_U, grad_div_u, div_sym_grad_u; for (unsigned int i = 0; i < NumNodes; i++) { const array_1d& r_acceleration = rGeom[i].FastGetSolutionStepValue(ACCELERATION); array_1d sigma_U = ZeroVector(Dim); + grad_div_u = ZeroVector(Dim); + div_sym_grad_u = ZeroVector(Dim); for (unsigned int d = 0; d < Dim; d++) { for (unsigned int e = 0; e < Dim; e++){ sigma_U[d] += sigma(d,e) * rData.N[i] * r_velocities(i,e); + grad_div_u[d] += rData.DDN_DDX[i](d,e) * r_velocities(i,e); + if (d == e) + div_sym_grad_u[d] += rData.DDN_DDX[i](e,e) * r_velocities(i,d); + else + div_sym_grad_u[d] += 1.0/2.0 * (rData.DDN_DDX[i](e,d) * r_velocities(i,e) + rData.DDN_DDX[i](e,e) * r_velocities(i,d)); } - rResidual[d] += density * ( rData.N[i]*(r_body_forces(i,d) - r_acceleration[d]) - convection[i]*r_velocities(i,d)) - - rData.DN_DX(i,d)*r_pressures[i] - sigma_U[d]; + rResidual[d] += density * ( rData.N[i]*(r_body_forces(i,d) - r_acceleration[d]) - convection[i]*r_velocities(i,d)) + 2.0 * viscosity * div_sym_grad_u[d] - 2.0/3.0 * viscosity * grad_div_u[d] - rData.DN_DX(i,d) * r_pressures[i] - sigma_U[d]; } } } @@ -192,22 +419,115 @@ void QSVMSDEMCoupled::MomentumProjTerm( const double density = this->GetAtCoordinate(rData.Density,rData.N); const double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; + const auto body_force = this->GetAtCoordinate(rData.BodyForce, rData.N); - sigma *= viscosity; + const auto r_velocities = rData.Velocity; + const auto r_pressures = rData.Pressure; + const auto velocity = this->GetAtCoordinate(rData.Velocity,rData.N); + Vector grad_div_u, div_sym_grad_u; for (unsigned int i = 0; i < NumNodes; i++) { - Vector sigma_U = ZeroVector(Dim); + array_1d sigma_U = ZeroVector(Dim); + grad_div_u = ZeroVector(Dim); + div_sym_grad_u = ZeroVector(Dim); for (unsigned int d = 0; d < Dim; d++) { for (unsigned int e = 0; e < Dim; e++){ - sigma_U[d] += sigma(d,e) * rData.N[i] * rData.Velocity(i,e); + sigma_U[d] += sigma(d,e) * rData.N[i] * r_velocities(i,e); + grad_div_u[d] += rData.DDN_DDX[i](d,e) * r_velocities(i,e); + if (d == e) + div_sym_grad_u[d] += rData.DDN_DDX[i](e,e) * r_velocities(i,d); + else + div_sym_grad_u[d] += 1.0/2.0 * (rData.DDN_DDX[i](e,d) * r_velocities(i,e) + rData.DDN_DDX[i](e,e) * r_velocities(i,d)); + } + rMomentumRHS[d] += density * (- AGradN[i]*r_velocities(i,d)) + 2.0 * viscosity * div_sym_grad_u[d] - 2.0/3.0 * viscosity * grad_div_u[d] - rData.DN_DX(i,d) * r_pressures[i] - sigma_U[d]; + } + } + for (unsigned int d = 0; d < Dim; d++) + rMomentumRHS[d] += density * body_force[d]; +} + +template +void QSVMSDEMCoupled::AddReactionStabilization( + TElementData& rData, + BoundedMatrix& rLHS, + VectorType& rLocalRHS) +{ + + const double density = this->GetAtCoordinate(rData.Density, rData.N); + + BoundedMatrix tau_one = ZeroMatrix(Dim, Dim); + double tau_two; + const array_1d convective_velocity = + this->GetAtCoordinate(rData.Velocity, rData.N) - + this->GetAtCoordinate(rData.MeshVelocity, rData.N); + + this->CalculateTau(rData, convective_velocity, tau_one, tau_two); + + array_1d body_force = density * this->GetAtCoordinate(rData.BodyForce, rData.N); + + Vector AGradN; + this->ConvectionOperator(AGradN, convective_velocity, rData.DN_DX); // Get a * grad(Ni) + + AGradN *= density; + + const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); + double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); + + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; + + // Note: Dof order is (vx,vy,[vz,]p) for each node + for (unsigned int i = 0; i < NumNodes; i++) + { + unsigned int row = i*BlockSize; + // Loop over columns + for (unsigned int j = 0; j < NumNodes; j++) + { + unsigned int col = j*BlockSize; + + for (unsigned int d = 0; d < Dim; d++) // iterate over dimensions for velocity Dofs in this node combination + { + double RSigmaG = 0.0; + double GAlphaR = 0.0; + for (unsigned int e = 0; e < Dim; e++){ + double ASigma = tau_one(d,d) * AGradN[i] * sigma(d,e) * rData.N[j]; + double RRSigma = 0.0; + double RSigmaA = tau_one(d,d) * sigma(d,e) * rData.N[i] * AGradN[j]; + double LSigma_1 = 0.0; + double LSigma_2 = 0.0; + double CSigma = 0.0; + double RSigmaL_1 = 0.0; + double RSigmaL_2 = 0.0; + double RSigmaC = 0.0; + GAlphaR += tau_one(d,d) * fluid_fraction * rData.DN_DX(i,e) * sigma(e,d) * rData.N[j]; + RSigmaG += tau_one(d,d) * sigma(d,e) * rData.N[i] * rData.DN_DX(j,e); + for (unsigned int f = 0; f < Dim; f++){ + LSigma_1 += tau_one(d,d) * viscosity * rData.DDN_DDX[i](f,f) * sigma(d,e) * rData.N[j]; + LSigma_2 += tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,f) * sigma(f,e) * rData.N[j]; + CSigma += 2.0/3.0 * tau_one(d,d) * viscosity * rData.DDN_DDX[i](f,d) * sigma(f,e) * rData.N[j]; + RRSigma += tau_one(d,d) * sigma(d,f) * rData.N[i] * sigma(f,e) * rData.N[j]; + RSigmaL_1 += tau_one(d,d) * viscosity * rData.N[i] * sigma(d,e) * rData.DDN_DDX[j](f,f); + RSigmaL_2 += tau_one(d,d) * viscosity * rData.N[i] * sigma(d,f) * rData.DDN_DDX[j](e,f); + RSigmaC += 2.0/3.0 * tau_one(d,d) * viscosity * sigma(d,f) * rData.N[i] * rData.DDN_DDX[j](f,e); + } + double LSigma = LSigma_1 + LSigma_2; + double RSigmaL = RSigmaL_1 + RSigmaL_2; + rLHS(row+d,col+e) += rData.Weight * (ASigma - RRSigma - RSigmaA - CSigma + LSigma - RSigmaL + RSigmaC); + } + rLHS(row+Dim,col+d) += rData.Weight * (GAlphaR); + rLHS(row+d,col+Dim) += rData.Weight * (-RSigmaG); + } + } + + // RHS terms + for (unsigned int d = 0; d < Dim; ++d) + { + double RSigmaF = 0.0; + for (unsigned int e = 0; e < Dim; ++e){ + RSigmaF += tau_one(d,d) * rData.N[i] * sigma(d,e) * body_force[e]; /*- momentum_projection[e]*/ //momentum_projection 0 because is ASGS } - rMomentumRHS[d] += density * ( rData.N[i]*(rData.BodyForce(i,d) /*- rAcc[d]*/) - AGradN[i]*rData.Velocity(i,d)) - - rData.DN_DX(i,d)*rData.Pressure[i] - sigma_U[d]; + rLocalRHS[row+d] += rData.Weight * (- RSigmaF); } } } @@ -238,34 +558,30 @@ void QSVMSDEMCoupled::AddMassStabilization( const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); double viscosity = this->GetAtCoordinate(rData.DynamicViscosity, rData.N); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); - - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); - sigma *= viscosity; + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; // Note: Dof order is (vx,vy,[vz,]p) for each node - for (unsigned int i = 0; i < NumNodes; ++i) + for (unsigned int i = 0; i < NumNodes; i++) { unsigned int row = i*BlockSize; - double divergence_convective = 0.0; - for (unsigned int d = 0; d < Dim; d++) { - divergence_convective += (rData.Velocity(i,d) - rData.MeshVelocity(i,d)) * rData.DN_DX(i,d); - } // Loop over columns - for (unsigned int j = 0; j < NumNodes; ++j) + for (unsigned int j = 0; j < NumNodes; j++) { unsigned int col = j*BlockSize; - for (unsigned int d = 0; d < Dim; ++d) // iterate over dimensions for velocity Dofs in this node combination + for (unsigned int d = 0; d < Dim; d++) // iterate over dimensions for velocity Dofs in this node combination { - double UGAlpha = tau_one(d,d) * (fluid_fraction * rData.DN_DX(i,d) * rData.N[j]); + double UGAlpha = tau_one(d,d) * fluid_fraction * rData.DN_DX(i,d) * rData.N[j]; double AU = tau_one(d,d) * AGradN[i] * rData.N[j]; - for (unsigned int e = 0; e < Dim; ++e){ - double RSigmaU = -tau_one(d,d) * sigma(d,e) * rData.N[i] * AGradN[j]; - rMassMatrix(row+d, col+e) += weight * RSigmaU; + for (unsigned int e = 0; e < Dim; e++){ + double LI = tau_one(d,d) * viscosity * rData.N[j] * rData.DDN_DDX[i](d,e); + double CI = 2.0/3.0 * tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,e) * rData.N[j]; + double RSigmaU = tau_one(d,d) * sigma(d,e) * rData.N[i] * rData.N[j]; + for (unsigned int f = 0; f < Dim; f++) + if (d == e) + LI += tau_one(d,d) * viscosity * rData.DDN_DDX[i](f,f) * rData.N[j]; + rMassMatrix(row+d, col+e) += weight * (LI - CI - RSigmaU); } rMassMatrix(row+d, col+d) += weight * AU; rMassMatrix(row+Dim,col+d) += weight * UGAlpha; @@ -274,26 +590,6 @@ void QSVMSDEMCoupled::AddMassStabilization( } } -template -void QSVMSDEMCoupled::AddMassRHS( - VectorType& rRightHandSideVector, - TElementData& rData) -{ - double fluid_fraction_rate = 0.0; - double mass_source = 0.0; - mass_source = this->GetAtCoordinate(rData.MassSource, rData.N); - fluid_fraction_rate = this->GetAtCoordinate(rData.FluidFractionRate, rData.N); - - // Add the results to the pressure components (Local Dofs are vx, vy, [vz,] p for each node) - int LocalIndex = Dim; - for (unsigned int i = 0; i < NumNodes; ++i){ - for (unsigned int d = 0; d < Dim;++d) - rRightHandSideVector[LocalIndex] -= rData.Weight * rData.N[i] * (fluid_fraction_rate - mass_source); - LocalIndex += Dim + 1; - } - -} - // Add a the contribution from a single integration point to the velocity contribution template< class TElementData > void QSVMSDEMCoupled::AddVelocitySystem( @@ -301,12 +597,13 @@ void QSVMSDEMCoupled::AddVelocitySystem( MatrixType& rLocalLHS, VectorType& rLocalRHS) { - auto& LHS = rData.LHS; + BoundedMatrix& LHS = rData.LHS; LHS.clear(); // Interpolate nodal data on the integration point const double density = this->GetAtCoordinate(rData.Density, rData.N); - const array_1d body_force = density * this->GetAtCoordinate(rData.BodyForce,rData.N); + array_1d body_force = density * this->GetAtCoordinate(rData.BodyForce,rData.N); // Force per unit of volume + const array_1d momentum_projection = this->GetAtCoordinate(rData.MomentumProjection, rData.N); double mass_projection = this->GetAtCoordinate(rData.MassProjection, rData.N); @@ -328,17 +625,12 @@ void QSVMSDEMCoupled::AddVelocitySystem( const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); const double fluid_fraction_rate = this->GetAtCoordinate(rData.FluidFractionRate, rData.N); const double mass_source = this->GetAtCoordinate(rData.MassSource, rData.N); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); - - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - sigma *= viscosity; + MatrixType sigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; // Temporary containers - double V, P, U, QD, DD, DU, RSigma, ASigma, RRSigma, RSigmaA; + //double U; // Note: Dof order is (u,v,[w,]p) for each node for (unsigned int i = 0; i < NumNodes; i++) @@ -346,51 +638,88 @@ void QSVMSDEMCoupled::AddVelocitySystem( unsigned int row = i*BlockSize; - double divergence_convective = 0.0; - for (unsigned int d = 0; d < Dim; d++) { - divergence_convective += (rData.Velocity(i,d) - rData.MeshVelocity(i,d)) * rData.DN_DX(i,d); - } - // LHS terms for (unsigned int j = 0; j < NumNodes; j++) { unsigned int col = j*BlockSize; // Some terms are the same for all velocity components, calculate them once for each i,j - V = rData.Weight * rData.N[i] * AGradN[j]; + double V = rData.N[i] * AGradN[j]; // q-p stabilization block (initialize result) double G = 0; for (unsigned int d = 0; d < Dim; d++) { + double AA = tau_one(d,d) * AGradN[i] * AGradN[j]; // Stabilization: u*grad(v) * tau_one * u*grad(u); // Stabilization: (a * Grad(v)) * tau_one * Grad(p) - P = rData.DN_DX(i,d) * rData.N[j]; // Div(v) * p - U = fluid_fraction_gradient[d] * rData.N[j] * rData.N[i]; - QD = fluid_fraction * rData.DN_DX(j,d) * rData.N[i]; - - double GAlphaR = 0.0; - double RSigmaG = 0.0; - double GAlphaA = tau_one(d,d) * AGradN[j] * fluid_fraction * rData.DN_DX(i,d); + double P = rData.DN_DX(i,d) * rData.N[j]; // Div(v) * p + double U = fluid_fraction_gradient[d] * rData.N[j] * rData.N[i]; + double QD = fluid_fraction * rData.N[i] * rData.DN_DX(j,d); + + double GAlphaA = tau_one(d,d) * fluid_fraction * rData.DN_DX(i,d) * AGradN[j]; + double GAlphaL_1 = 0.0; + double GAlphaL_2 = 0.0; + double GAlphaC = 0.0; double AG = tau_one(d,d) * AGradN[i] * rData.DN_DX(j,d); + double LG_1 = 0.0; + double LG_2 = 0.0; + double CG = 0.0; G += tau_one(d,d) * fluid_fraction * rData.DN_DX(i,d) * rData.DN_DX(j,d); - double AA = rData.Weight * tau_one(d,d) * AGradN[j] * AGradN[i]; // Stabilization: u*grad(v) * tau_one * u*grad(u); - for (unsigned int e = 0; e < Dim; e++){ // Stabilization: Div(v) * tau_two * Div(u) - RSigma = rData.N[i] * sigma(d,e) * rData.N[j]; - ASigma = tau_one(d,d) * AGradN[i] * sigma(d,e) * rData.N[j]; - RRSigma = tau_one(d,d) * sigma(d,e) * rData.N[i] * sigma(e,d) * rData.N[j]; - RSigmaA = tau_one(d,d) * sigma(d,e) * rData.N[i] * AGradN[j]; - DD = tau_two * fluid_fraction * rData.DN_DX(i,d) * rData.DN_DX(j,e); - DU = tau_two * rData.DN_DX(i,d) * fluid_fraction_gradient[e] * rData.N[j]; - GAlphaR += tau_one(d,d) * fluid_fraction * rData.DN_DX(i,d) * sigma(d,e) * rData.N[j]; - RSigmaG += tau_one(d,d) * sigma(d,e) * rData.N[i] * rData.DN_DX(j,d); - LHS(row+d,col+e) += rData.Weight * (DD + DU + RSigma + ASigma + RRSigma + RSigmaA); + double DnuD = 2.0/3.0 * viscosity * rData.DN_DX(i,d) * rData.DN_DX(j,e); + double GS = viscosity * rData.DN_DX(i,e) * rData.DN_DX(j,d); + double DU = tau_two * rData.DN_DX(i,d) * fluid_fraction_gradient[e] * rData.N[j]; + double DD = tau_two * fluid_fraction * rData.DN_DX(i,d) * rData.DN_DX(j,e); + double RSigma = rData.N[i] * sigma(d,e) * rData.N[j]; + double AL = tau_one(d,d) * viscosity * AGradN[i] * rData.DDN_DDX[j](d,e); + double AC = 2.0 / 3.0 * tau_one(d,d) * viscosity * AGradN[i] * rData.DDN_DDX[j](d,e); + double LA = tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,e) * AGradN[j]; + double LL_diag_1 = 0.0; + double LL_diag_2 = 0.0; + double LL_2 = 0.0; + double LL_3 = 0.0; + double LL_4 = 0.0; + double LC_1 = 0.0; + double LC_2 = 0.0; + double CA = 2.0/3.0 * tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,e) * AGradN[j]; + double CL_1 = 0.0; + double CL_2 = 0.0; + double CC = 0.0; + GAlphaL_1 += tau_one(d,d) * viscosity * fluid_fraction * rData.DN_DX(i,d) * rData.DDN_DDX[j](e,e); + GAlphaL_2 += tau_one(d,d) * viscosity * fluid_fraction * rData.DN_DX(i,e) * rData.DDN_DDX[j](d,e); + GAlphaC += 2.0/3.0 * tau_one(d,d) * viscosity * fluid_fraction * rData.DN_DX(i,e) * rData.DDN_DDX[j](e,d); + LG_1 += tau_one(d,d) * viscosity * rData.DDN_DDX[i](e,e) * rData.DN_DX(j,d); + LG_2 += tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,e) * rData.DN_DX(j,e); + CG += 2.0/3.0 * tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,e) * rData.DN_DX(j,e); + for (unsigned int f = 0; f < Dim; f++){ + if (d == e){ + GS += viscosity * rData.DN_DX(i,f) * rData.DN_DX(j,f); + AL += tau_one(d,d) * viscosity * AGradN[i] * rData.DDN_DDX[j](f,f); + LA += tau_one(d,d) * viscosity * rData.DDN_DDX[i](f,f) * AGradN[j]; + LL_diag_1 += tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](f,f); + LL_diag_2 += rData.DDN_DDX[j](f,f); + } + LL_2 += tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](f,f) * rData.DDN_DDX[j](d,e); + LL_3 += tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](d,e) * rData.DDN_DDX[j](f,f); + LL_4 += tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](d,f) * rData.DDN_DDX[j](e,f); + LC_1 += 2.0/3.0 * tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](f,f) * rData.DDN_DDX[j](d,e); + LC_2 += 2.0/3.0 * tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](d,f) * rData.DDN_DDX[j](f,e); + CL_2 += 2.0/3.0 * tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](d,f) * rData.DDN_DDX[j](f,e); + CL_1 += 2.0/3.0 * tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](d,e) * rData.DDN_DDX[j](f,f); + CC += 4.0/9.0 * tau_one(d,d) * viscosity * viscosity * rData.DDN_DDX[i](f,d) * rData.DDN_DDX[j](f,e); + } + double LL = (LL_diag_1 * LL_diag_2) + LL_2 + LL_3 + LL_4; + double LC = LC_1 + LC_2; + double CL = CL_1 + CL_2; + LHS(row+d,col+e) += rData.Weight * (GS - DnuD - AL + AC + LA - LL + LC - CA + CL - CC + DD + DU + RSigma); } + double GAlphaL = GAlphaL_1 + GAlphaL_2; + double LG = LG_1 + LG_2; - LHS(row+d,col+d) += V + AA; - LHS(row+Dim,col+d) += rData.Weight * (GAlphaA + U + QD + GAlphaR); - LHS(row+d,col+Dim) += rData.Weight * (AG - P + RSigmaG); + LHS(row+d,col+d) += rData.Weight * (V + AA); + LHS(row+Dim,col+d) += rData.Weight * (GAlphaA + U + QD - GAlphaL + GAlphaC); + LHS(row+d,col+Dim) += rData.Weight * (AG - P + LG - CG); } // Write q-p term @@ -403,14 +732,26 @@ void QSVMSDEMCoupled::AddVelocitySystem( double Q = rData.N[i] * (mass_source - fluid_fraction_rate); for (unsigned int d = 0; d < Dim; ++d) { + double VF = rData.N[i] * body_force[d]; double AF = tau_one(d,d) * AGradN[i] * (body_force[d] - momentum_projection[d]); - double DPhi = tau_two * rData.DN_DX(i,d) * (mass_projection + mass_source - fluid_fraction_rate); - rLocalRHS[row+d] += rData.Weight * rData.N[i] * body_force[d]; // v*BodyForce - rLocalRHS[row+d] += rData.Weight * (AF + DPhi); + double DPhi = tau_two * rData.DN_DX(i,d) * (mass_source - fluid_fraction_rate - mass_projection); + double LF_1 = 0.0; + double LF_2 = 0.0; + double CF = 0.0; QAlphaF += tau_one(d,d) * fluid_fraction * rData.DN_DX(i,d) * (body_force[d] - momentum_projection[d]); + for (unsigned int e = 0; e < Dim; ++e){ + LF_1 += tau_one(d,d) * viscosity * rData.DDN_DDX[i](e,e) * (body_force[d] - momentum_projection[d]); + LF_2 += tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,e) * (body_force[e] - momentum_projection[e]); + CF += 2.0/3.0 * tau_one(d,d) * viscosity * rData.DDN_DDX[i](d,e) * (body_force[e] - momentum_projection[e]); + } + double LF = LF_1 + LF_2; + rLocalRHS[row+d] += rData.Weight * (VF + AF + LF - CF + DPhi); } rLocalRHS[row+Dim] += rData.Weight * (QAlphaF + Q); } + // Adding reactive terms to the stabilization + if(!rData.UseOSS) + this->AddReactionStabilization(rData,LHS,rLocalRHS); // Write (the linearized part of the) local contribution into residual form (A*dx = b - A*x) array_1d values; @@ -420,12 +761,131 @@ void QSVMSDEMCoupled::AddVelocitySystem( * For a generic (potentially non-linear) constitutive law, one cannot assume that RHS = F - LHS*current_values. * Because of this, the AddViscousTerm function manages both the LHS and the RHS. */ - this->AddViscousTerm(rData, LHS, rLocalRHS); + //this->AddViscousTerm(rData, LHS, rLocalRHS); noalias(rLocalLHS) += LHS; } +template +void QSVMSDEMCoupled::CalculateMassMatrix(MatrixType& rMassMatrix, + const ProcessInfo& rCurrentProcessInfo) +{ + // Resize and intialize output + if (rMassMatrix.size1() != LocalSize) + rMassMatrix.resize(LocalSize, LocalSize, false); + + noalias(rMassMatrix) = ZeroMatrix(LocalSize, LocalSize); + + if (!TElementData::ElementManagesTimeIntegration) { + // Get Shape function data + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + DenseVector> shape_function_second_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); + const unsigned int number_of_gauss_points = gauss_weights.size(); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + // Iterate over integration points to evaluate local contribution + for (unsigned int g = 0; g < number_of_gauss_points; g++) { + this->UpdateIntegrationPointDataSecondDerivatives( + data, g, gauss_weights[g], + row(shape_functions, g),shape_derivatives[g],shape_function_second_derivatives[g]); + + this->AddMassLHS(data, rMassMatrix); + } + } +} + +template +void QSVMSDEMCoupled::CalculateLocalVelocityContribution(MatrixType& rDampMatrix, + VectorType& rRightHandSideVector, + const ProcessInfo& rCurrentProcessInfo) +{ + // Resize and intialize output + if( rDampMatrix.size1() != LocalSize ) + rDampMatrix.resize(LocalSize,LocalSize,false); + + if( rRightHandSideVector.size() != LocalSize ) + rRightHandSideVector.resize(LocalSize,false); + + noalias(rDampMatrix) = ZeroMatrix(LocalSize,LocalSize); + noalias(rRightHandSideVector) = ZeroVector(LocalSize); + + if (!TElementData::ElementManagesTimeIntegration) { + // Get Shape function data + Vector gauss_weights; + Matrix shape_functions; + ShapeFunctionDerivativesArrayType shape_derivatives; + DenseVector> shape_function_second_derivatives; + this->CalculateGeometryData( + gauss_weights, shape_functions, shape_derivatives); + const unsigned int number_of_gauss_points = gauss_weights.size(); + + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + shape_function_second_derivatives,this->GetGeometry(),this->GetIntegrationMethod()); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + // Iterate over integration points to evaluate local contribution + for (unsigned int g = 0; g < number_of_gauss_points; g++) { + const auto& r_dndx = shape_derivatives[g]; + this->UpdateIntegrationPointDataSecondDerivatives( + data, g, gauss_weights[g], + row(shape_functions, g),r_dndx, shape_function_second_derivatives[g]); + this->AddVelocitySystem(data, rDampMatrix, rRightHandSideVector); + } + } +} + +template < class TElementData > +void QSVMSDEMCoupled::CalculateResistanceTensor( + const TElementData& rData) +{ + BoundedMatrix& rsigma = mViscousResistanceTensor[rData.IntegrationPointIndex]; + + BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); + + rsigma = permeability; +} + +template< class TElementData > +void QSVMSDEMCoupled::AddMassLHS( + TElementData& rData, + MatrixType &rMassMatrix) +{ + const double density = this->GetAtCoordinate(rData.Density,rData.N); + // Note: Dof order is (u,v,[w,]p) for each node + for (unsigned int i = 0; i < NumNodes; i++) + { + unsigned int row = i*BlockSize; + for (unsigned int j = 0; j < NumNodes; j++) + { + unsigned int col = j*BlockSize; + const double Mij = rData.Weight * density * rData.N[i] * rData.N[j]; + for (unsigned int d = 0; d < Dim; d++) + rMassMatrix(row+d,col+d) += Mij; + } + } + + /* Note on OSS and full projection: Riccardo says that adding the terms provided by + * AddMassStabilization (and incluiding their corresponding terms in the projeciton) + * could help reduce the non-linearity of the coupling between projection and u,p + * However, leaving them on gives a lot of trouble whith the Bossak scheme: + * think that we solve F - (1-alpha)*M*u^(n+1) - alpha*M*u^(n) - K(u^(n+1)) = 0 + * so the projection of the dynamic terms should be Pi( (1-alpha)*u^(n+1) - alpha*u^(n) ) + */ + if (!rData.UseOSS) + this->AddMassStabilization(rData,rMassMatrix); +} + template void QSVMSDEMCoupled::MassProjTerm( const TElementData& rData, @@ -442,7 +902,7 @@ void QSVMSDEMCoupled::MassProjTerm( for (unsigned int i = 0; i < NumNodes; i++) { for (unsigned int d = 0; d < Dim; ++d) { - rMassRHS -= (fluid_fraction * rData.DN_DX(i, d) * velocities(i, d)) + fluid_fraction_gradient[d] * rData.N[i] * velocities(i, d); + rMassRHS -= (fluid_fraction * rData.DN_DX(i, d) * velocities(i, d) + fluid_fraction_gradient[d] * rData.N[i] * velocities(i, d)); } } rMassRHS += mass_source - fluid_fraction_rate; @@ -455,39 +915,100 @@ void QSVMSDEMCoupled::CalculateTau( BoundedMatrix &TauOne, double &TauTwo) const { - double tau_one; - double inv_tau; constexpr double c1 = 8.0; constexpr double c2 = 2.0; - + const int p = mInterpolationOrder; const double h = rData.ElementSize; const double density = this->GetAtCoordinate(rData.Density,rData.N); const double viscosity = this->GetAtCoordinate(rData.EffectiveViscosity,rData.N); - double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); - BoundedMatrix permeability = this->GetAtCoordinate(rData.Permeability, rData.N); - BoundedMatrix sigma = ZeroMatrix(Dim, Dim); + const double fluid_fraction = this->GetAtCoordinate(rData.FluidFraction, rData.N); + MatrixType sigma = ZeroMatrix(Dim+1, Dim+1); BoundedMatrix I = IdentityMatrix(Dim, Dim); - BoundedMatrix eigen_values_matrix, eigen_vectors_matrix; + array_1d fluid_fraction_gradient = this->GetAtCoordinate(rData.FluidFractionGradient, rData.N); - double det_permeability = MathUtils::Det(permeability); - MathUtils::InvertMatrix(permeability, sigma, det_permeability, -1.0); + double velocity_modulus = 0.0; + double fluid_fraction_gradient_modulus = 0.0; - double velocity_norm = 0.0; - double sigma_term = 0.0; for (unsigned int d = 0; d < Dim; d++){ - velocity_norm += Velocity[d]*Velocity[d]; - for (unsigned int e = d; e < Dim; e++){ - sigma_term += std::pow(sigma(d,e),2); - } + velocity_modulus += Velocity[d] * Velocity[d]; + fluid_fraction_gradient_modulus += std::pow(fluid_fraction_gradient[d],2); + sigma(d,d) = mViscousResistanceTensor[rData.IntegrationPointIndex](d,d); } - velocity_norm = std::sqrt(velocity_norm); - inv_tau = c1 * viscosity / (h*h) + density * (c2 * velocity_norm / h ) + std::sqrt(sigma_term); + double velocity_norm = std::sqrt(velocity_modulus); + double fluid_fraction_gradient_norm = std::sqrt(fluid_fraction_gradient_modulus); - tau_one = 1 / inv_tau; + double c_alpha = 1.0 + h / c1 * fluid_fraction_gradient_norm; + + double inv_tau_NS = c1 * viscosity / std::pow(h/(p*p),2.0) + density * (c2 * velocity_norm / (h/p) ); + double tau_one_NS = 1.0 / inv_tau_NS; + + double inv_tau = inv_tau_NS * c_alpha; + //inv_tau = c1 * viscosity / (h*h) + density * (c2 * velocity_norm / h ); + + double tau_one = 1 / (inv_tau + sigma(0,0)); TauOne = tau_one * I; - TauTwo = h * h / (c1 * fluid_fraction * tau_one); + TauTwo = std::pow(h/p,2.0) / (c1 * fluid_fraction * tau_one_NS); +} + +template< class TElementData > +void QSVMSDEMCoupled::CalculateProjections(const ProcessInfo &rCurrentProcessInfo) +{ + // Get Shape function data + + DenseVector> ShapeFunctionSecondDerivatives; + Vector GaussWeights; + Matrix ShapeFunctions; + ShapeFunctionDerivativesArrayType ShapeDerivatives; + this->CalculateGeometryData(GaussWeights,ShapeFunctions,ShapeDerivatives); + const long unsigned int NumGauss = GaussWeights.size(); + + GeometryType& r_geometry = this->GetGeometry(); + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + ShapeFunctionSecondDerivatives,this->GetGeometry(),this->GetIntegrationMethod()); + + TElementData data; + data.Initialize(*this, rCurrentProcessInfo); + + array_1d momentum_rhs = ZeroVector(NumNodes*Dim); + VectorType MassRHS = ZeroVector(NumNodes); + VectorType NodalArea = ZeroVector(NumNodes); + + for (unsigned int g = 0; g < NumGauss; g++) + { + this->UpdateIntegrationPointDataSecondDerivatives(data, g, GaussWeights[g], row(ShapeFunctions, g), ShapeDerivatives[g],ShapeFunctionSecondDerivatives[g]); + + array_1d MomentumRes = ZeroVector(3); + double MassRes = 0.0; + array_1d convective_velocity = this->GetAtCoordinate(data.Velocity,data.N) - this->GetAtCoordinate(data.MeshVelocity,data.N); + + this->MomentumProjTerm(data, convective_velocity, MomentumRes); + this->MassProjTerm(data,MassRes); + + for (unsigned int i = 0; i < NumNodes; i++) + { + double W = data.Weight*data.N[i]; + unsigned int row = i*Dim; + for (unsigned int d = 0; d < Dim; d++) + momentum_rhs[row+d] += W*MomentumRes[d]; + MassRHS[i] += W*MassRes; + NodalArea[i] += data.Weight*data.N[i]; + } + } + + // Add carefully to nodal variables to avoid OpenMP race condition + for (SizeType i = 0; i < NumNodes; ++i) + { + r_geometry[i].SetLock(); // So it is safe to write in the node in OpenMP + array_1d& rMomValue = r_geometry[i].FastGetSolutionStepValue(ADVPROJ); + unsigned int row = i*Dim; + for (unsigned int d = 0; d < Dim; d++) + rMomValue[d] += momentum_rhs[row+d]; + r_geometry[i].FastGetSolutionStepValue(NODAL_AREA) += NodalArea[i]; + r_geometry[i].FastGetSolutionStepValue(DIVPROJ) += MassRHS[i]; + r_geometry[i].UnSetLock(); // Free the node for other threads + } } template< class TElementData > @@ -533,6 +1054,43 @@ void QSVMSDEMCoupled::SubscalePressure( rPressureSubscale = tau_two*Residual; } +template< class TElementData > +void QSVMSDEMCoupled::UpdateSubscaleVelocity( + const TElementData& rData) +{ + array_1d predicted_subscale_velocity; + + array_1d previous_velocity = mPreviousVelocity[rData.IntegrationPointIndex]; + + //for (size_t i = 0; i < NumNodes; i++) { + array_1d subscale_velocity_on_previous_iteration = mPredictedSubscaleVelocity[rData.IntegrationPointIndex]; + + array_1d v_d = ZeroVector(3); + + for (unsigned int d = 0; d < Dim; d++) + v_d[d] = previous_velocity[d] + subscale_velocity_on_previous_iteration[d]; + + // Part of the residual that does not depend on the subscale + array_1d static_residual = ZeroVector(3); + + if (!rData.UseOSS) + this->AlgebraicMomentumResidual(rData,v_d,static_residual); + else + this->OrthogonalMomentumResidual(rData,v_d,static_residual); + + + BoundedMatrix tau_one = ZeroMatrix(Dim, Dim); + double tau_two; + + this->CalculateTau(rData,v_d,tau_one,tau_two); + + for (unsigned int d = 0; d < Dim; d++) + predicted_subscale_velocity[d] = tau_one(d,d) * static_residual[d]; + + noalias(mPredictedSubscaleVelocity[rData.IntegrationPointIndex]) = predicted_subscale_velocity; + +} + /////////////////////////////////////////////////////////////////////////////////////////////////// // Private functions /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -561,6 +1119,9 @@ template class QSVMSDEMCoupled >; template class QSVMSDEMCoupled >; template class QSVMSDEMCoupled< QSVMSDEMCoupledData<2,4> >; -template class QSVMSDEMCoupled< QSVMSDEMCoupledData<3,8> >; -} +template class QSVMSDEMCoupled< QSVMSDEMCoupledData<2,6> >; +template class QSVMSDEMCoupled< QSVMSDEMCoupledData<2,9> >; +template class QSVMSDEMCoupled< QSVMSDEMCoupledData<3,8> >; +template class QSVMSDEMCoupled< QSVMSDEMCoupledData<3,27> >; +} \ No newline at end of file diff --git a/applications/FluidDynamicsApplication/custom_elements/qs_vms_dem_coupled.h b/applications/FluidDynamicsApplication/custom_elements/qs_vms_dem_coupled.h index a63f376ebd55..e805e92dc9e5 100644 --- a/applications/FluidDynamicsApplication/custom_elements/qs_vms_dem_coupled.h +++ b/applications/FluidDynamicsApplication/custom_elements/qs_vms_dem_coupled.h @@ -100,6 +100,8 @@ class QSVMSDEMCoupled : public QSVMS /// Type for an array of shape function gradient matrices typedef GeometryType::ShapeFunctionsGradientsType ShapeFunctionDerivativesArrayType; + typedef GeometryType::ShapeFunctionsSecondDerivativesType ShapeFunctionsSecondDerivativesType; + constexpr static unsigned int Dim = QSVMS::Dim; constexpr static unsigned int NumNodes = QSVMS::NumNodes; constexpr static unsigned int BlockSize = QSVMS::BlockSize; @@ -179,6 +181,10 @@ class QSVMSDEMCoupled : public QSVMS GeometryType::Pointer pGeom, Properties::Pointer pProperties) const override; + void Initialize(const ProcessInfo& rCurrentProcessInfo) override; + + GeometryData::IntegrationMethod GetIntegrationMethod() const override; + void Calculate( const Variable& rVariable, double& rOutput, @@ -189,11 +195,31 @@ class QSVMSDEMCoupled : public QSVMS array_1d& rOutput, const ProcessInfo& rCurrentProcessInfo) override; + void CalculateOnIntegrationPoints( + const Variable>& rVariable, + std::vector>& rOutput, + const ProcessInfo& rCurrentProcessInfo) override; + + void CalculateOnIntegrationPoints( + const Variable& rVariable, + std::vector& rOutput, + const ProcessInfo& rCurrentProcessInfo) override; + + void CalculateOnIntegrationPoints( + Variable const& rVariable, + std::vector& rValues, + ProcessInfo const& rCurrentProcessInfo) override; + + void InitializeNonLinearIteration(const ProcessInfo& rCurrentProcessInfo) override; + + void FinalizeNonLinearIteration(const ProcessInfo& rCurrentProcessInfo) override; + + void UpdateSubscaleVelocity(const TElementData& rData); + void EquationIdVector( EquationIdVectorType& rResult, const ProcessInfo& rCurrentProcessInfo) const override; - void CalculateRightHandSide( VectorType& rRightHandSideVector, const ProcessInfo& rCurrentProcessInfo) override; @@ -236,7 +262,11 @@ class QSVMSDEMCoupled : public QSVMS ///@} ///@name Protected member Variables ///@{ - + int mInterpolationOrder = 1; + DenseVector > mViscousResistanceTensor; + // Velocity subscale history, stored at integration points + DenseVector< array_1d > mPredictedSubscaleVelocity; + DenseVector< array_1d > mPreviousVelocity; ///@} ///@name Protected Operators @@ -259,6 +289,11 @@ class QSVMSDEMCoupled : public QSVMS const array_1d& rConvectionVelocity, array_1d &rMomentumRHS) const override; + void AddReactionStabilization( + TElementData& rData, + BoundedMatrix& rLHS, + VectorType& rLocalRHS); + void AddMassStabilization( TElementData& rData, MatrixType &rMassMatrix); @@ -270,14 +305,35 @@ class QSVMSDEMCoupled : public QSVMS BoundedMatrix &TauOne, double &TauTwo) const; + void CalculateProjections( + const ProcessInfo &rCurrentProcessInfo) override; + + void UpdateIntegrationPointDataSecondDerivatives( + TElementData& rData, + unsigned int IntegrationPointIndex, + double Weight, + const typename TElementData::MatrixRowType& rN, + const typename TElementData::ShapeDerivativesType& rDN_DX, + const typename TElementData::ShapeFunctionsSecondDerivativesType& rDDN_DDX) const; + void AddVelocitySystem( TElementData& rData, MatrixType &rLocalLHS, VectorType &rLocalRHS) override; - void AddMassRHS( - VectorType& rRightHandSideVector, - TElementData& rData); + void CalculateMassMatrix(MatrixType& rMassMatrix, + const ProcessInfo& rCurrentProcessInfo) override; + + void CalculateLocalVelocityContribution(MatrixType& rDampMatrix, + VectorType& rRightHandSideVector, + const ProcessInfo& rCurrentProcessInfo) override; + + void CalculateResistanceTensor( + const TElementData& rData); + + void AddMassLHS( + TElementData& rData, + MatrixType& rMassMatrix) override; void MassProjTerm( const TElementData& rData, diff --git a/applications/FluidDynamicsApplication/custom_utilities/fluid_element_data.cpp b/applications/FluidDynamicsApplication/custom_utilities/fluid_element_data.cpp index 6dfd48a56873..30c5b0a9ab8f 100644 --- a/applications/FluidDynamicsApplication/custom_utilities/fluid_element_data.cpp +++ b/applications/FluidDynamicsApplication/custom_utilities/fluid_element_data.cpp @@ -201,6 +201,8 @@ template class FluidElementData<2,3,true>; // Quadrilaterals template class FluidElementData<2,4,false>; +template class FluidElementData<2,6,false>; +template class FluidElementData<2,9,false>; template class FluidElementData<2,4,true>; // Tetrahedra @@ -214,5 +216,6 @@ template class FluidElementData<3,6,true>; // Hexahedra template class FluidElementData<3,8,false>; template class FluidElementData<3,8,true>; +template class FluidElementData<3,27,false>; } // namespace Kratos diff --git a/applications/FluidDynamicsApplication/custom_utilities/fluid_element_utilities.cpp b/applications/FluidDynamicsApplication/custom_utilities/fluid_element_utilities.cpp index d5edc97ac964..7cff740a047e 100644 --- a/applications/FluidDynamicsApplication/custom_utilities/fluid_element_utilities.cpp +++ b/applications/FluidDynamicsApplication/custom_utilities/fluid_element_utilities.cpp @@ -226,8 +226,10 @@ void FluidElementUtilities::DenseSystemSolve( template class FluidElementUtilities<3>; // triangle3 template class FluidElementUtilities<4>; // tetrahedra4, quadrilateral4 +template class FluidElementUtilities<9>; // quadrilateral9 template class FluidElementUtilities<6>; // prism template class FluidElementUtilities<8>; // hexahedra8 +template class FluidElementUtilities<27>; // hexahedra27 /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/applications/FluidDynamicsApplication/custom_utilities/qsvms_dem_coupled_data.h b/applications/FluidDynamicsApplication/custom_utilities/qsvms_dem_coupled_data.h index 34ebdc1fef05..b1c40a3e903f 100644 --- a/applications/FluidDynamicsApplication/custom_utilities/qsvms_dem_coupled_data.h +++ b/applications/FluidDynamicsApplication/custom_utilities/qsvms_dem_coupled_data.h @@ -18,6 +18,7 @@ // External includes // Project includes +#include "geometries/geometry.h" #include "utilities/element_size_calculator.h" #include "includes/checks.h" @@ -42,9 +43,19 @@ class QSVMSDEMCoupledData : public QSVMSData::NodalScalarData; using NodalVectorData = typename FluidElementData::NodalVectorData; using NodalTensorData = typename FluidElementData::NodalTensorData; +using ShapeFunctionsSecondDerivativesType = DenseVector; +using MatrixRowType = MatrixRow; +using ShapeDerivativesType = BoundedMatrix; ///@} ///@name Public Members @@ -60,6 +71,8 @@ NodalVectorData BodyForce; NodalTensorData Permeability; +ShapeFunctionsSecondDerivativesType DDN_DDX; + double ElementSize; ///@} @@ -81,7 +94,13 @@ void Initialize( this->FillFromHistoricalNodalData(Acceleration, ACCELERATION, r_geometry); this->FillFromHistoricalNodalData(BodyForce,BODY_FORCE,r_geometry); - ElementSize = ElementSizeCalculator::MinimumElementSize(r_geometry); + ElementSize = ElementSizeCalculator::AverageElementSize(r_geometry); +} + +void UpdateSecondDerivativesValues(const ShapeFunctionsSecondDerivativesType& rDDN_DDX) +{ + ShapeFunctionsSecondDerivativesType& ddn_ddx = this->DDN_DDX; + ddn_ddx = rDDN_DDX; } ///@} diff --git a/applications/FluidDynamicsApplication/fluid_dynamics_application.cpp b/applications/FluidDynamicsApplication/fluid_dynamics_application.cpp index 8c3ea191d075..ddae22ff039f 100644 --- a/applications/FluidDynamicsApplication/fluid_dynamics_application.cpp +++ b/applications/FluidDynamicsApplication/fluid_dynamics_application.cpp @@ -17,6 +17,7 @@ // Project includes #include "includes/define.h" #include "geometries/triangle_2d_3.h" +#include "geometries/triangle_2d_6.h" #include "geometries/triangle_3d_3.h" #include "geometries/tetrahedra_3d_4.h" #include "geometries/quadrilateral_2d_4.h" @@ -41,11 +42,15 @@ KratosFluidDynamicsApplication::KratosFluidDynamicsApplication(): mQSVMSDEMCoupled2D3N(0, Element::GeometryType::Pointer(new Triangle2D3(Element::GeometryType::PointsArrayType(3)))), mQSVMSDEMCoupled3D4N(0, Element::GeometryType::Pointer(new Tetrahedra3D4(Element::GeometryType::PointsArrayType(4)))), mQSVMSDEMCoupled2D4N(0, Element::GeometryType::Pointer(new Quadrilateral2D4(Element::GeometryType::PointsArrayType(4)))), + mQSVMSDEMCoupled2D9N(0, Element::GeometryType::Pointer(new Quadrilateral2D9(Element::GeometryType::PointsArrayType(9)))), mQSVMSDEMCoupled3D8N(0, Element::GeometryType::Pointer(new Hexahedra3D8(Element::GeometryType::PointsArrayType(8)))), mAlternativeQSVMSDEMCoupled2D3N(0, Element::GeometryType::Pointer(new Triangle2D3(Element::GeometryType::PointsArrayType(3)))), + mAlternativeQSVMSDEMCoupled2D6N(0, Element::GeometryType::Pointer(new Triangle2D6(Element::GeometryType::PointsArrayType(6)))), mAlternativeQSVMSDEMCoupled3D4N(0, Element::GeometryType::Pointer(new Tetrahedra3D4(Element::GeometryType::PointsArrayType(4)))), mAlternativeQSVMSDEMCoupled2D4N(0, Element::GeometryType::Pointer(new Quadrilateral2D4(Element::GeometryType::PointsArrayType(4)))), + mAlternativeQSVMSDEMCoupled2D9N(0, Element::GeometryType::Pointer(new Quadrilateral2D9(Element::GeometryType::PointsArrayType(9)))), mAlternativeQSVMSDEMCoupled3D8N(0, Element::GeometryType::Pointer(new Hexahedra3D8(Element::GeometryType::PointsArrayType(8)))), + mAlternativeQSVMSDEMCoupled3D27N(0, Element::GeometryType::Pointer(new Hexahedra3D27(Element::GeometryType::PointsArrayType(27)))), mTimeIntegratedQSVMS2D3N(0, Element::GeometryType::Pointer(new Triangle2D3(Element::GeometryType::PointsArrayType(3)))), mTimeIntegratedQSVMS3D4N(0, Element::GeometryType::Pointer(new Tetrahedra3D4(Element::GeometryType::PointsArrayType(4)))), mAxisymmetricNavierStokes2D3N(0, Element::GeometryType::Pointer(new Triangle2D3(Element::GeometryType::PointsArrayType(3)))), @@ -55,11 +60,14 @@ KratosFluidDynamicsApplication::KratosFluidDynamicsApplication(): mDVMSDEMCoupled2D3N(0, Element::GeometryType::Pointer(new Triangle2D3(Element::GeometryType::PointsArrayType(3)))), mDVMSDEMCoupled3D4N(0, Element::GeometryType::Pointer(new Tetrahedra3D4(Element::GeometryType::PointsArrayType(4)))), mDVMSDEMCoupled2D4N(0, Element::GeometryType::Pointer(new Quadrilateral2D4(Element::GeometryType::PointsArrayType(4)))), + mDVMSDEMCoupled2D9N(0, Element::GeometryType::Pointer(new Quadrilateral2D9(Element::GeometryType::PointsArrayType(9)))), mDVMSDEMCoupled3D8N(0, Element::GeometryType::Pointer(new Hexahedra3D8(Element::GeometryType::PointsArrayType(8)))), mAlternativeDVMSDEMCoupled2D3N(0, Element::GeometryType::Pointer(new Triangle2D3(Element::GeometryType::PointsArrayType(3)))), mAlternativeDVMSDEMCoupled3D4N(0, Element::GeometryType::Pointer(new Tetrahedra3D4(Element::GeometryType::PointsArrayType(4)))), mAlternativeDVMSDEMCoupled2D4N(0, Element::GeometryType::Pointer(new Quadrilateral2D4(Element::GeometryType::PointsArrayType(4)))), + mAlternativeDVMSDEMCoupled2D9N(0, Element::GeometryType::Pointer(new Quadrilateral2D9(Element::GeometryType::PointsArrayType(9)))), mAlternativeDVMSDEMCoupled3D8N(0, Element::GeometryType::Pointer(new Hexahedra3D8(Element::GeometryType::PointsArrayType(8)))), + mAlternativeDVMSDEMCoupled3D27N(0, Element::GeometryType::Pointer(new Hexahedra3D27(Element::GeometryType::PointsArrayType(27)))), mFIC2D3N(0, Element::GeometryType::Pointer(new Triangle2D3(Element::GeometryType::PointsArrayType(3)))), mFIC2D4N(0, Element::GeometryType::Pointer(new Quadrilateral2D4(Element::GeometryType::PointsArrayType(4)))), mFIC3D4N(0, Element::GeometryType::Pointer(new Tetrahedra3D4(Element::GeometryType::PointsArrayType(4)))), @@ -279,11 +287,15 @@ void KratosFluidDynamicsApplication::Register() { KRATOS_REGISTER_ELEMENT("QSVMSDEMCoupled2D3N",mQSVMSDEMCoupled2D3N); KRATOS_REGISTER_ELEMENT("QSVMSDEMCoupled3D4N",mQSVMSDEMCoupled3D4N); KRATOS_REGISTER_ELEMENT("QSVMSDEMCoupled2D4N",mQSVMSDEMCoupled2D4N); + KRATOS_REGISTER_ELEMENT("QSVMSDEMCoupled2D9N",mQSVMSDEMCoupled2D9N); KRATOS_REGISTER_ELEMENT("QSVMSDEMCoupled3D8N",mQSVMSDEMCoupled3D8N); KRATOS_REGISTER_ELEMENT("AlternativeQSVMSDEMCoupled2D3N",mAlternativeQSVMSDEMCoupled2D3N); + KRATOS_REGISTER_ELEMENT("AlternativeQSVMSDEMCoupled2D6N",mAlternativeQSVMSDEMCoupled2D6N); KRATOS_REGISTER_ELEMENT("AlternativeQSVMSDEMCoupled3D4N",mAlternativeQSVMSDEMCoupled3D4N); KRATOS_REGISTER_ELEMENT("AlternativeQSVMSDEMCoupled2D4N",mAlternativeQSVMSDEMCoupled2D4N); + KRATOS_REGISTER_ELEMENT("AlternativeQSVMSDEMCoupled2D9N",mAlternativeQSVMSDEMCoupled2D9N); KRATOS_REGISTER_ELEMENT("AlternativeQSVMSDEMCoupled3D8N",mAlternativeQSVMSDEMCoupled3D8N); + KRATOS_REGISTER_ELEMENT("AlternativeQSVMSDEMCoupled3D27N",mAlternativeQSVMSDEMCoupled3D27N); KRATOS_REGISTER_ELEMENT("TimeIntegratedQSVMS2D3N",mTimeIntegratedQSVMS2D3N); KRATOS_REGISTER_ELEMENT("TimeIntegratedQSVMS3D4N",mTimeIntegratedQSVMS3D4N); KRATOS_REGISTER_ELEMENT("AxisymmetricNavierStokes2D3N",mAxisymmetricNavierStokes2D3N); @@ -293,11 +305,14 @@ void KratosFluidDynamicsApplication::Register() { KRATOS_REGISTER_ELEMENT("DVMSDEMCoupled2D3N",mDVMSDEMCoupled2D3N); KRATOS_REGISTER_ELEMENT("DVMSDEMCoupled3D4N",mDVMSDEMCoupled3D4N); KRATOS_REGISTER_ELEMENT("DVMSDEMCoupled2D4N",mDVMSDEMCoupled2D4N); + KRATOS_REGISTER_ELEMENT("DVMSDEMCoupled2D9N",mDVMSDEMCoupled2D9N); KRATOS_REGISTER_ELEMENT("DVMSDEMCoupled3D8N",mDVMSDEMCoupled3D8N); KRATOS_REGISTER_ELEMENT("AlternativeDVMSDEMCoupled2D3N",mAlternativeDVMSDEMCoupled2D3N); KRATOS_REGISTER_ELEMENT("AlternativeDVMSDEMCoupled3D4N",mAlternativeDVMSDEMCoupled3D4N); KRATOS_REGISTER_ELEMENT("AlternativeDVMSDEMCoupled2D4N",mAlternativeDVMSDEMCoupled2D4N); + KRATOS_REGISTER_ELEMENT("AlternativeDVMSDEMCoupled2D9N",mAlternativeDVMSDEMCoupled2D9N); KRATOS_REGISTER_ELEMENT("AlternativeDVMSDEMCoupled3D8N",mAlternativeDVMSDEMCoupled3D8N); + KRATOS_REGISTER_ELEMENT("AlternativeDVMSDEMCoupled3D27N",mAlternativeDVMSDEMCoupled3D27N); KRATOS_REGISTER_ELEMENT("FIC2D3N",mFIC2D3N); KRATOS_REGISTER_ELEMENT("FIC2D4N",mFIC2D4N); KRATOS_REGISTER_ELEMENT("FIC3D4N",mFIC3D4N); diff --git a/applications/FluidDynamicsApplication/fluid_dynamics_application.h b/applications/FluidDynamicsApplication/fluid_dynamics_application.h index cc3e5c634a97..3ffcc70a6b4c 100644 --- a/applications/FluidDynamicsApplication/fluid_dynamics_application.h +++ b/applications/FluidDynamicsApplication/fluid_dynamics_application.h @@ -280,13 +280,19 @@ class KRATOS_API(FLUID_DYNAMICS_APPLICATION) KratosFluidDynamicsApplication : pu const QSVMS< QSVMSData<2,4> > mQSVMS2D4N; const QSVMS< QSVMSData<3,8> > mQSVMS3D8N; const QSVMSDEMCoupled< QSVMSDEMCoupledData<2,3> > mQSVMSDEMCoupled2D3N; + const QSVMSDEMCoupled< QSVMSDEMCoupledData<2,6> > mQSVMSDEMCoupled2D6N; const QSVMSDEMCoupled< QSVMSDEMCoupledData<3,4> > mQSVMSDEMCoupled3D4N; const QSVMSDEMCoupled< QSVMSDEMCoupledData<2,4> > mQSVMSDEMCoupled2D4N; + const QSVMSDEMCoupled< QSVMSDEMCoupledData<2,9> > mQSVMSDEMCoupled2D9N; const QSVMSDEMCoupled< QSVMSDEMCoupledData<3,8> > mQSVMSDEMCoupled3D8N; + const QSVMSDEMCoupled< QSVMSDEMCoupledData<3,27> > mQSVMSDEMCoupled3D27N; const AlternativeQSVMSDEMCoupled< QSVMSDEMCoupledData<2,3> > mAlternativeQSVMSDEMCoupled2D3N; + const AlternativeQSVMSDEMCoupled< QSVMSDEMCoupledData<2,6> > mAlternativeQSVMSDEMCoupled2D6N; const AlternativeQSVMSDEMCoupled< QSVMSDEMCoupledData<3,4> > mAlternativeQSVMSDEMCoupled3D4N; const AlternativeQSVMSDEMCoupled< QSVMSDEMCoupledData<2,4> > mAlternativeQSVMSDEMCoupled2D4N; + const AlternativeQSVMSDEMCoupled< QSVMSDEMCoupledData<2,9> > mAlternativeQSVMSDEMCoupled2D9N; const AlternativeQSVMSDEMCoupled< QSVMSDEMCoupledData<3,8> > mAlternativeQSVMSDEMCoupled3D8N; + const AlternativeQSVMSDEMCoupled< QSVMSDEMCoupledData<3,27> > mAlternativeQSVMSDEMCoupled3D27N; const QSVMS< TimeIntegratedQSVMSData<2,3> > mTimeIntegratedQSVMS2D3N; const QSVMS< TimeIntegratedQSVMSData<3,4> > mTimeIntegratedQSVMS3D4N; const AxisymmetricNavierStokes< AxisymmetricNavierStokesData<2,3> > mAxisymmetricNavierStokes2D3N; @@ -294,13 +300,19 @@ class KRATOS_API(FLUID_DYNAMICS_APPLICATION) KratosFluidDynamicsApplication : pu const DVMS< QSVMSData<2,3> > mDVMS2D3N; const DVMS< QSVMSData<3,4> > mDVMS3D4N; const DVMSDEMCoupled< QSVMSDEMCoupledData<2,3> > mDVMSDEMCoupled2D3N; + const DVMSDEMCoupled< QSVMSDEMCoupledData<2,6> > mDVMSDEMCoupled2D6N; const DVMSDEMCoupled< QSVMSDEMCoupledData<3,4> > mDVMSDEMCoupled3D4N; const DVMSDEMCoupled< QSVMSDEMCoupledData<2,4> > mDVMSDEMCoupled2D4N; + const DVMSDEMCoupled< QSVMSDEMCoupledData<2,9> > mDVMSDEMCoupled2D9N; const DVMSDEMCoupled< QSVMSDEMCoupledData<3,8> > mDVMSDEMCoupled3D8N; + const DVMSDEMCoupled< QSVMSDEMCoupledData<3,27> > mDVMSDEMCoupled3D27N; const AlternativeDVMSDEMCoupled< QSVMSDEMCoupledData<2,3> > mAlternativeDVMSDEMCoupled2D3N; + const AlternativeDVMSDEMCoupled< QSVMSDEMCoupledData<2,6> > mAlternativeDVMSDEMCoupled2D6N; const AlternativeDVMSDEMCoupled< QSVMSDEMCoupledData<3,4> > mAlternativeDVMSDEMCoupled3D4N; const AlternativeDVMSDEMCoupled< QSVMSDEMCoupledData<2,4> > mAlternativeDVMSDEMCoupled2D4N; + const AlternativeDVMSDEMCoupled< QSVMSDEMCoupledData<2,9> > mAlternativeDVMSDEMCoupled2D9N; const AlternativeDVMSDEMCoupled< QSVMSDEMCoupledData<3,8> > mAlternativeDVMSDEMCoupled3D8N; + const AlternativeDVMSDEMCoupled< QSVMSDEMCoupledData<3,27> > mAlternativeDVMSDEMCoupled3D27N; const FIC< FICData<2,3> > mFIC2D3N; const FIC< FICData<2,4> > mFIC2D4N; const FIC< FICData<3,4> > mFIC3D4N; diff --git a/applications/FluidDynamicsApplication/tests/cpp_tests/test_alternative_d_vms_dem_coupled_element.cpp b/applications/FluidDynamicsApplication/tests/cpp_tests/test_alternative_d_vms_dem_coupled_element.cpp index 413918690b5b..0e1d6773987c 100644 --- a/applications/FluidDynamicsApplication/tests/cpp_tests/test_alternative_d_vms_dem_coupled_element.cpp +++ b/applications/FluidDynamicsApplication/tests/cpp_tests/test_alternative_d_vms_dem_coupled_element.cpp @@ -77,7 +77,7 @@ KRATOS_TEST_CASE_IN_SUITE(AlternativeDVMSDEMCoupled2D4N, FluidDynamicsApplicatio Matrix& r_permeability = it_node->FastGetSolutionStepValue(PERMEABILITY); r_permeability = ZeroMatrix(Dim, Dim); for (unsigned int d = 0; d < Dim; ++d){ - r_permeability(d,d) = 1.0e+30; + r_permeability(d,d) = 0.0; } } @@ -115,22 +115,43 @@ KRATOS_TEST_CASE_IN_SUITE(AlternativeDVMSDEMCoupled2D4N, FluidDynamicsApplicatio Vector RHS = ZeroVector(12); Matrix LHS = ZeroMatrix(12,12); - std::vector output = {6.28653,8.05611,-0.0592958,-6.10046,5.68718,-0.0474501,-8.28656,-7.63009,-0.0403475,5.07712,-9.13657,-0.0529065}; // DVMSDEMCoupled2D4N + std::vector output = {2.885342223,3.817976395,-0.05954391544,-3.764678983,2.452222894,-0.04746809897,-5.675304236,-5.32981538,-0.04009093622,1.144992949,-6.350031955,-0.05289704936}; // AlternativeDVMSDEMCoupled2D4N for (ModelPart::ElementIterator i = model_part.ElementsBegin(); i != model_part.ElementsEnd(); i++) { const auto& r_process_info = model_part.GetProcessInfo(); i->Initialize(r_process_info); // Initialize constitutive law const auto& rElem = *i; rElem.Check(r_process_info); + i->InitializeNonLinearIteration(r_process_info); i->CalculateLocalVelocityContribution(LHS, RHS, r_process_info); - //std::cout.precision(10); - //std::cout << i->Info() << RHS << std::endl; - //KRATOS_WATCH(RHS); + + // std::cout << i->Info() << std::setprecision(10) << std::endl; + // KRATOS_WATCH(RHS); for (unsigned int j = 0; j < output.size(); j++) { KRATOS_EXPECT_NEAR(RHS[j], output[j], 1e-5); } } + double porosity = 0.5; + for (ModelPart::NodeIterator it_node=model_part.NodesBegin(); it_nodeFastGetSolutionStepValue(FLUID_FRACTION); + r_fluid_fraction = porosity; + Matrix& r_permeability = it_node->FastGetSolutionStepValue(PERMEABILITY); + r_permeability = ZeroMatrix(Dim, Dim); + } + + for (ModelPart::ElementIterator i = model_part.ElementsBegin(); i != model_part.ElementsEnd(); i++) { + const auto& r_process_info = model_part.GetProcessInfo(); + i->Initialize(r_process_info); // Initialize constitutive law + const auto& rElem = *i; + rElem.Check(r_process_info); + i->InitializeNonLinearIteration(r_process_info); + i->CalculateLocalVelocityContribution(LHS, RHS, r_process_info); + + for (unsigned int j = 0; j < output.size(); j++) { + KRATOS_CHECK_NEAR(RHS[j], porosity*output[j], 1e-5); + } + } } } // namespace Testing diff --git a/applications/FluidDynamicsApplication/tests/cpp_tests/test_alternative_qs_vms_dem_coupled_element.cpp b/applications/FluidDynamicsApplication/tests/cpp_tests/test_alternative_qs_vms_dem_coupled_element.cpp index 5883e015bf5d..858e1dc12b3f 100644 --- a/applications/FluidDynamicsApplication/tests/cpp_tests/test_alternative_qs_vms_dem_coupled_element.cpp +++ b/applications/FluidDynamicsApplication/tests/cpp_tests/test_alternative_qs_vms_dem_coupled_element.cpp @@ -21,6 +21,8 @@ // Application includes #include "custom_constitutive/newtonian_2d_law.h" +#include "custom_elements/alternative_qs_vms_dem_coupled.h" +#include "custom_utilities/qsvms_dem_coupled_data.h" namespace Kratos { namespace Testing { @@ -51,13 +53,13 @@ KRATOS_TEST_CASE_IN_SUITE(AlternativeQSVMSDEMCoupled2D4N, FluidDynamicsApplicati // Process info creation double delta_time = 0.1; - model_part.GetProcessInfo().SetValue(DYNAMIC_TAU, 0.001); model_part.GetProcessInfo().SetValue(DELTA_TIME, delta_time); // Set the element properties Properties::Pointer p_properties = model_part.CreateNewProperties(0); p_properties->SetValue(DENSITY, 1000.0); - p_properties->SetValue(DYNAMIC_VISCOSITY, 1.0e-05); + p_properties->SetValue(DYNAMIC_VISCOSITY, 1.0e-5); + p_properties->SetValue(DYNAMIC_TAU, 0.0); ConstitutiveLaw::Pointer pConsLaw(new Newtonian2DLaw()); p_properties->SetValue(CONSTITUTIVE_LAW, pConsLaw); @@ -77,7 +79,7 @@ KRATOS_TEST_CASE_IN_SUITE(AlternativeQSVMSDEMCoupled2D4N, FluidDynamicsApplicati Matrix& r_permeability = it_node->FastGetSolutionStepValue(PERMEABILITY); r_permeability = ZeroMatrix(Dim, Dim); for (unsigned int d = 0; d < Dim; ++d){ - r_permeability(d,d) = 1.0e+30; + r_permeability(d,d) = 0.0; } } @@ -115,7 +117,7 @@ KRATOS_TEST_CASE_IN_SUITE(AlternativeQSVMSDEMCoupled2D4N, FluidDynamicsApplicati Vector RHS = ZeroVector(12); Matrix LHS = ZeroMatrix(12,12); - std::vector output = {9.64354,11.4131,0.0252164,-11.1519,0.635718,-0.0535359,-31.9278,-31.2713,-0.106665,-14.2305,-28.4442,-0.0650155}; // QSVMSDEMCoupled2D4N + std::vector output = {-0.7903859428,0.1422482204,-0.01715539615,-10.404201,-4.187299126,-0.05064119836,-21.69732287,-21.35183401,-0.07314514572,-14.77475686,-22.26978176,-0.05905825977}; // QSVMSDEMCoupled2D4N for (ModelPart::ElementIterator i = model_part.ElementsBegin(); i != model_part.ElementsEnd(); i++) { const auto& r_process_info = model_part.GetProcessInfo(); @@ -124,14 +126,224 @@ KRATOS_TEST_CASE_IN_SUITE(AlternativeQSVMSDEMCoupled2D4N, FluidDynamicsApplicati const auto& rElem = *i; rElem.Check(r_process_info); i->CalculateLocalVelocityContribution(LHS, RHS, r_process_info); - - //std::cout << i->Info() << std::setprecision(10) << std::endl; - //KRATOS_WATCH(RHS); + // std::cout << i->Info() << std::setprecision(10) << std::endl; + // KRATOS_WATCH(RHS); for (unsigned int j = 0; j < output.size(); j++) { KRATOS_EXPECT_NEAR(RHS[j], output[j], 1e-4); } } + double porosity = 0.5; + for (ModelPart::NodeIterator it_node=model_part.NodesBegin(); it_nodeFastGetSolutionStepValue(FLUID_FRACTION); + r_fluid_fraction = porosity; + Matrix& r_permeability = it_node->FastGetSolutionStepValue(PERMEABILITY); + r_permeability = ZeroMatrix(Dim, Dim); + } + + for (ModelPart::ElementIterator i = model_part.ElementsBegin(); i != model_part.ElementsEnd(); i++) { + const auto& r_process_info = model_part.GetProcessInfo(); + i->Initialize(r_process_info); // Initialize constitutive law + const auto& rElem = *i; + rElem.Check(r_process_info); + i->CalculateLocalVelocityContribution(LHS, RHS, r_process_info); + + for (unsigned int j = 0; j < output.size(); j++) { + KRATOS_CHECK_NEAR(RHS[j], porosity*output[j], 1e-5); + } + } +} + +KRATOS_TEST_CASE_IN_SUITE(SecondShapeDerivativesInterpolation3D, FluidDynamicsApplicationFastSuite) +{ + Model model; + const double buffer_size = 2; + const unsigned int Dim = 3; + ModelPart& model_part = model.CreateModelPart("Main",buffer_size); + + // Set the element properties + Properties::Pointer p_properties = model_part.CreateNewProperties(0); + + // Square creation + model_part.CreateNewNode(1, 0.0, 0.0, 0.0); + model_part.CreateNewNode(2, 0.0, 0.0, 0.05); + model_part.CreateNewNode(3, 0.05,0.0,0.0); + model_part.CreateNewNode(4, 0.0, 0.05, 0.0); + model_part.CreateNewNode(5, 0.05, 0.0, 0.05); + model_part.CreateNewNode(6, 0.05, 0.05, 0.0); + model_part.CreateNewNode(7, 0.0, 0.05, 0.05); + model_part.CreateNewNode(8, 0.05, 0.05, 0.05); + model_part.CreateNewNode(9, 0.0, 0.1, 0.0); + model_part.CreateNewNode(10, 0.0, 0.0, 0.1); + model_part.CreateNewNode(11, 0.1, 0.0, 0.0); + model_part.CreateNewNode(12, 0.05, 0.1, 0.0); + model_part.CreateNewNode(13, 0.0, 0.1, 0.05); + model_part.CreateNewNode(14, 0.0, 0.05, 0.1); + model_part.CreateNewNode(15, 0.05, 0.0, 0.1); + model_part.CreateNewNode(16, 0.1, 0.0, 0.05); + model_part.CreateNewNode(17, 0.1, 0.05, 0.0); + model_part.CreateNewNode(18, 0.05, 0.1, 0.05); + model_part.CreateNewNode(19, 0.05, 0.05, 0.1); + model_part.CreateNewNode(20, 0.1, 0.05, 0.05); + model_part.CreateNewNode(21, 0.1, 0.1, 0.0); + model_part.CreateNewNode(22, 0.1, 0.0, 0.1); + model_part.CreateNewNode(23, 0.0, 0.1, 0.1); + model_part.CreateNewNode(25, 0.1, 0.1, 0.05); + model_part.CreateNewNode(26, 0.05, 0.1, 0.1); + model_part.CreateNewNode(29, 0.1, 0.05, 0.1); + model_part.CreateNewNode(39, 0.1, 0.1, 0.1); + + + std::vector element_nodes {39, 23, 9, 21, 22, 10, 1, 11, 26, 13, 12, 25, 29, 14, 4, 17, 15, 2, 3, 16, 18, 19, 7, 6, 20, 5, 8}; + model_part.CreateNewElement("AlternativeQSVMSDEMCoupled3D27N", 1, element_nodes, p_properties); + + + for (ModelPart::ElementIterator i_elem = model_part.ElementsBegin(); i_elem != model_part.ElementsEnd(); i_elem++) { + auto& rElement = *i_elem; + + Matrix exact_hess(Dim,Dim); + + DenseVector> DDN_DDX; + + const unsigned int NumNodes = rElement.GetGeometry().PointsNumber(); + + AlternativeQSVMSDEMCoupled>* p_element = dynamic_cast>*>(&rElement); + const Geometry::IntegrationMethod integration_method = p_element->GetIntegrationMethod(); + + + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + DDN_DDX,rElement.GetGeometry(),rElement.GetIntegrationMethod()); + + Matrix NContainer = p_element->GetGeometry().ShapeFunctionsValues(integration_method); + + const Geometry::IntegrationPointsArrayType integration_points = p_element->GetGeometry().IntegrationPoints(integration_method); + const unsigned int number_of_integration_points = integration_points.size(); + + Matrix gauss_point_coordinates = ZeroMatrix(number_of_integration_points,Dim); + + for(unsigned int g = 0; g < number_of_integration_points; g++){ + Matrix hess = ZeroMatrix(Dim, Dim); + Matrix Hessian(Dim, Dim); + for (unsigned int i = 0; i < NumNodes; ++i){ + const array_1d& r_coordinates = p_element->GetGeometry()[i].Coordinates(); + const double x1 = r_coordinates[0]; + const double x2 = r_coordinates[1]; + const double x3 = r_coordinates[2]; + + const auto r_pressure = std::pow(x1,2)*std::pow(x2,2) + std::pow(x1,2)*std::pow(x3,2) + std::pow(x2,2)*std::pow(x3,2) + std::pow(x1,2)*x2 + std::pow(x1,2)*x3 + std::pow(x2,2)*x1 + std::pow(x2,2)*x3 + std::pow(x3,2)*x1 + std::pow(x3,2)*x2 + std::pow(x1,2) + std::pow(x2,2) + std::pow(x3,2) + x1*x2*x3 + x1*x2 + x2*x3 + x1*x3 + x1 + x2 + x3 + 1.0; + for (unsigned int d = 0; d < Dim; ++d){ + gauss_point_coordinates(g,d) += NContainer(g,i) * r_coordinates[d]; + for (unsigned int e = 0; e < Dim; ++e){ + hess(d,e) += DDN_DDX[g][i](d,e) * r_pressure; + } + } + } + + const double x1 = gauss_point_coordinates(g,0); + const double x2 = gauss_point_coordinates(g,1); + const double x3 = gauss_point_coordinates(g,2); + + exact_hess(0,0) = 2.0 * std::pow(x2,2) + 2.0 * std::pow(x3,2) + 2.0 * x2 + 2.0 * x3 + 2.0; + exact_hess(0,1) = 4.0 * x1 * x2 + 2.0 * x1 + 2.0 * x2 + x3 + 1.0; + exact_hess(0,2) = 4.0 * x1 * x3 + 2.0 * x1 + 2.0 * x3 + x2 + 1.0; + exact_hess(1,0) = 4.0 * x1 * x2 + 2.0 * x1 + 2.0 * x2 + x3 + 1.0; + exact_hess(1,1) = 2.0 * std::pow(x1,2) + 2.0 * std::pow(x3,2) + 2.0 * x1 + 2.0 * x3 + 2.0; + exact_hess(1,2) = 4.0 * x2 * x3 + 2.0 * x2 + 2.0 * x3 + x1 + 1.0; + exact_hess(2,0) = 4.0 * x1 * x3 + 2.0 * x1 + 2.0 * x3 + x2 + 1.0; + exact_hess(2,1) = 4.0 * x3 * x2 + 2.0 * x3 + 2.0 * x2 + x1 + 1.0; + exact_hess(2,2) = 2.0 * std::pow(x1,2) + 2.0 * std::pow(x2,2) + 2.0 * x1 + 2.0 * x2 + 2.0; + + for (unsigned int d = 0; d < Dim; ++d){ + for (unsigned int e = 0; e < Dim; ++e){ + KRATOS_CHECK_NEAR(hess(d,e), exact_hess(d,e),1e-10); + } + } + } + + } +} + +KRATOS_TEST_CASE_IN_SUITE(SecondShapeDerivativesInterpolation, FluidDynamicsApplicationFastSuite) +{ + Model model; + const double buffer_size = 2; + const unsigned int Dim = 2; + ModelPart& model_part = model.CreateModelPart("Main",buffer_size); + + // Set the element properties + Properties::Pointer p_properties = model_part.CreateNewProperties(0); + + // Square creation + model_part.CreateNewNode(1, 0.0, 0.0125, 0.0); + model_part.CreateNewNode(2, 0.0, 0.00625, 0.0); + model_part.CreateNewNode(3, 0.00625,0.0125,0.0); + model_part.CreateNewNode(4, 0.00625, 0.00625, 0.0); + model_part.CreateNewNode(5, 0.0, 0.0, 0.0); + model_part.CreateNewNode(6, 0.00625, 0.0, 0.0); + model_part.CreateNewNode(7, 0.0125, 0.0125, 0.0); + model_part.CreateNewNode(8, 0.0125, 0.00625, 0.0); + model_part.CreateNewNode(9, 0.0125, 0.0, 0.0); + + + std::vector element_nodes {9, 7, 1, 5, 8, 3, 2, 6, 4}; + model_part.CreateNewElement("AlternativeQSVMSDEMCoupled2D9N", 1, element_nodes, p_properties); + + + for (ModelPart::ElementIterator i_elem = model_part.ElementsBegin(); i_elem != model_part.ElementsEnd(); i_elem++) { + auto& rElement = *i_elem; + + Matrix exact_hess(Dim,Dim); + + DenseVector> DDN_DDX; + + const unsigned int NumNodes = rElement.GetGeometry().PointsNumber(); + + AlternativeQSVMSDEMCoupled>* p_element = dynamic_cast>*>(&rElement); + const Geometry::IntegrationMethod integration_method = p_element->GetIntegrationMethod(); + + GeometryUtils::ShapeFunctionsSecondDerivativesTransformOnAllIntegrationPoints( + DDN_DDX, p_element->GetGeometry(), p_element->GetIntegrationMethod()); + + Matrix NContainer = p_element->GetGeometry().ShapeFunctionsValues(integration_method); + + const Geometry::IntegrationPointsArrayType integration_points = p_element->GetGeometry().IntegrationPoints(integration_method); + const unsigned int number_of_integration_points = integration_points.size(); + + Matrix gauss_point_coordinates = ZeroMatrix(number_of_integration_points,Dim); + + for(unsigned int g = 0; g < number_of_integration_points; g++){ + Matrix hess = ZeroMatrix(Dim, Dim); + Matrix Hessian(Dim, Dim); + for (unsigned int i = 0; i < NumNodes; ++i){ + const array_1d& r_coordinates = p_element->GetGeometry()[i].Coordinates(); + const double x1 = r_coordinates[0]; + const double x2 = r_coordinates[1]; + + const auto r_pressure = std::pow(x1,2)*std::pow(x2,2) + std::pow(x1,2)*x2 + std::pow(x2,2)*x1 + std::pow(x1,2) + std::pow(x2,2) + x1*x2 + x1 + x2 + 1.0; + for (unsigned int d = 0; d < Dim; ++d){ + gauss_point_coordinates(g,d) += NContainer(g,i) * r_coordinates[d]; + for (unsigned int e = 0; e < Dim; ++e){ + hess(d,e) += DDN_DDX[g][i](d,e) * r_pressure; + } + } + } + + const double x1 = gauss_point_coordinates(g,0); + const double x2 = gauss_point_coordinates(g,1); + + exact_hess(0,0) = 2.0 * std::pow(x2,2) + 2.0 * x2 + 2.0; + exact_hess(0,1) = 4.0 * x1 * x2 + 2.0 * x1 + 2.0 * x2 + 1.0; + exact_hess(1,0) = 4.0 * x1 * x2 + 2.0 * x1 + 2.0 * x2 + 1.0; + exact_hess(1,1) = 2.0 * std::pow(x1,2) + 2.0 * x1 + 2.0; + + for (unsigned int d = 0; d < Dim; ++d){ + for (unsigned int e = 0; e < Dim; ++e){ + KRATOS_CHECK_NEAR(hess(d,e), exact_hess(d,e),1e-10); + } + } + } + + } } } // namespace Testing diff --git a/applications/FluidDynamicsApplication/tests/cpp_tests/test_d_vms_dem_coupled_element.cpp b/applications/FluidDynamicsApplication/tests/cpp_tests/test_d_vms_dem_coupled_element.cpp index d50463488085..8f3ef3bc7301 100644 --- a/applications/FluidDynamicsApplication/tests/cpp_tests/test_d_vms_dem_coupled_element.cpp +++ b/applications/FluidDynamicsApplication/tests/cpp_tests/test_d_vms_dem_coupled_element.cpp @@ -75,9 +75,6 @@ KRATOS_TEST_CASE_IN_SUITE(DVMSDEMCoupled2D4N, FluidDynamicsApplicationFastSuite) r_fluid_fraction = 1.0; Matrix& r_permeability = it_node->FastGetSolutionStepValue(PERMEABILITY); r_permeability = ZeroMatrix(Dim, Dim); - for (unsigned int d = 0; d < Dim; ++d){ - r_permeability(d,d) = 1.0e+30; - } } std::vector element_nodes {1, 2, 4, 3}; @@ -114,21 +111,43 @@ KRATOS_TEST_CASE_IN_SUITE(DVMSDEMCoupled2D4N, FluidDynamicsApplicationFastSuite) Vector RHS = ZeroVector(12); Matrix LHS = ZeroMatrix(12,12); - std::vector output = {6.286527961,8.056113874,-0.05929579635,-6.100463608,5.687177253,-0.04745013508,-8.286558938,-7.630094687,-0.04034752758,5.077121113,-9.136569912,-0.05290654099}; // DVMSDEMCoupled2D4N + std::vector output = {2.885342223,3.817976395,-0.05954391544,-3.764678983,2.452222894,-0.04746809897,-5.675304236,-5.32981538,-0.04009093622,1.144992949,-6.350031955,-0.05289704936}; // DVMSDEMCoupled2D4N for (ModelPart::ElementIterator i = model_part.ElementsBegin(); i != model_part.ElementsEnd(); i++) { const auto& r_process_info = model_part.GetProcessInfo(); i->Initialize(r_process_info); // Initialize constitutive law + const auto& rElem = *i; + rElem.Check(r_process_info); + i->InitializeNonLinearIteration(r_process_info); + i->CalculateLocalVelocityContribution(LHS, RHS, r_process_info); + + // std::cout << i->Info() << std::setprecision(10) << std::endl; + // KRATOS_WATCH(RHS); + + for (unsigned int j = 0; j < output.size(); j++) { + KRATOS_CHECK_NEAR(RHS[j], output[j], 1e-5); + } + } + double porosity = 0.5; + for (ModelPart::NodeIterator it_node=model_part.NodesBegin(); it_nodeFastGetSolutionStepValue(FLUID_FRACTION); + r_fluid_fraction = porosity; + } + for (ModelPart::ElementIterator i = model_part.ElementsBegin(); i != model_part.ElementsEnd(); i++) { + const auto& r_process_info = model_part.GetProcessInfo(); + i->Initialize(r_process_info); // Initialize constitutive law const auto& rElem = *i; rElem.Check(r_process_info); + i->InitializeNonLinearIteration(r_process_info); i->CalculateLocalVelocityContribution(LHS, RHS, r_process_info); - std::cout.precision(10); - //std::cout << i->Info() << RHS << std::endl; - //KRATOS_WATCH(RHS); for (unsigned int j = 0; j < output.size(); j++) { - KRATOS_EXPECT_NEAR(RHS[j], output[j], 1e-6); + if ((j+1) % (Dim+1) == 0){ + KRATOS_CHECK_NEAR(RHS[j], porosity*output[j], 1e-4);} + else{ + KRATOS_CHECK_NEAR(RHS[j], output[j], 1e-4);} + } } } diff --git a/applications/FluidDynamicsApplication/tests/cpp_tests/test_qs_vms_dem_coupled_element.cpp b/applications/FluidDynamicsApplication/tests/cpp_tests/test_qs_vms_dem_coupled_element.cpp index a03f5cce5e51..549060159150 100644 --- a/applications/FluidDynamicsApplication/tests/cpp_tests/test_qs_vms_dem_coupled_element.cpp +++ b/applications/FluidDynamicsApplication/tests/cpp_tests/test_qs_vms_dem_coupled_element.cpp @@ -51,7 +51,6 @@ KRATOS_TEST_CASE_IN_SUITE(QSVMSDEMCoupled2D4N, FluidDynamicsApplicationFastSuite // Process info creation double delta_time = 0.1; - model_part.GetProcessInfo().SetValue(DYNAMIC_TAU, 0.001); model_part.GetProcessInfo().SetValue(DELTA_TIME, delta_time); // Set the element properties @@ -76,9 +75,6 @@ KRATOS_TEST_CASE_IN_SUITE(QSVMSDEMCoupled2D4N, FluidDynamicsApplicationFastSuite r_fluid_fraction = 1.0; Matrix& r_permeability = it_node->FastGetSolutionStepValue(PERMEABILITY); r_permeability = ZeroMatrix(Dim, Dim); - for (unsigned int d = 0; d < Dim; ++d){ - r_permeability(d,d) = 1.0e+30; - } } std::vector element_nodes {1, 2, 4, 3}; @@ -115,7 +111,7 @@ KRATOS_TEST_CASE_IN_SUITE(QSVMSDEMCoupled2D4N, FluidDynamicsApplicationFastSuite Vector RHS = ZeroVector(12); Matrix LHS = ZeroMatrix(12,12); - std::vector output = {9.643535313,11.41312123,0.02521635855,-11.1519233,0.6357175579,-0.05353592744,-31.92778769,-31.27132344,-0.1066649361,-14.23049099,-28.44418201,-0.06501549498}; // QSVMSDEMCoupled2D4N + std::vector output = {-0.7903859428,0.1422482204,-0.01715539615,-10.404201,-4.187299126,-0.05064119836,-21.69732287,-21.35183401,-0.07314514572,-14.77475686,-22.26978176,-0.05905825977}; // QSVMSDEMCoupled2D4N for (ModelPart::ElementIterator i = model_part.ElementsBegin(); i != model_part.ElementsEnd(); i++) { const auto& r_process_info = model_part.GetProcessInfo(); @@ -125,13 +121,33 @@ KRATOS_TEST_CASE_IN_SUITE(QSVMSDEMCoupled2D4N, FluidDynamicsApplicationFastSuite rElem.Check(r_process_info); i->CalculateLocalVelocityContribution(LHS, RHS, r_process_info); - //std::cout << i->Info() << std::setprecision(10) << std::endl; - //KRATOS_WATCH(RHS); + // std::cout << i->Info() << std::setprecision(10) << std::endl; + // KRATOS_WATCH(RHS); for (unsigned int j = 0; j < output.size(); j++) { KRATOS_EXPECT_NEAR(RHS[j], output[j], 1e-4); } } + double porosity = 0.5; + for (ModelPart::NodeIterator it_node=model_part.NodesBegin(); it_nodeFastGetSolutionStepValue(FLUID_FRACTION); + r_fluid_fraction = porosity; + } + + for (ModelPart::ElementIterator i = model_part.ElementsBegin(); i != model_part.ElementsEnd(); i++) { + const auto& r_process_info = model_part.GetProcessInfo(); + i->Initialize(r_process_info); // Initialize constitutive law + const auto& rElem = *i; + rElem.Check(r_process_info); + i->CalculateLocalVelocityContribution(LHS, RHS, r_process_info); + + for (unsigned int j = 0; j < output.size(); j++) { + if ((j+1) % (Dim+1) == 0){ + KRATOS_CHECK_NEAR(RHS[j], porosity*output[j], 1e-4);} + else{ + KRATOS_CHECK_NEAR(RHS[j], output[j], 1e-4);} + } + } } } // namespace Testing diff --git a/applications/SwimmingDEMApplication/custom_strategies/strategies/bdf2_turbulent_schemeDEMCoupled.h b/applications/SwimmingDEMApplication/custom_strategies/strategies/bdf2_turbulent_schemeDEMCoupled.h index 1785a9856435..b5fa261e32de 100644 --- a/applications/SwimmingDEMApplication/custom_strategies/strategies/bdf2_turbulent_schemeDEMCoupled.h +++ b/applications/SwimmingDEMApplication/custom_strategies/strategies/bdf2_turbulent_schemeDEMCoupled.h @@ -162,7 +162,7 @@ class BDF2TurbulentSchemeDEMCoupled : public BDF2TurbulentSchemeUpdateFluidFraction(rModelPart, CurrentProcessInfo); + this->UpdateFluidFraction(rModelPart, CurrentProcessInfo); } void SetTimeCoefficients(ProcessInfo& rCurrentProcessInfo) diff --git a/applications/SwimmingDEMApplication/tests/drag_tests/chien_law/FluidMaterials.json b/applications/SwimmingDEMApplication/tests/drag_tests/chien_law/FluidMaterials.json index e9f7f76e03f8..dfae600aa6e4 100644 --- a/applications/SwimmingDEMApplication/tests/drag_tests/chien_law/FluidMaterials.json +++ b/applications/SwimmingDEMApplication/tests/drag_tests/chien_law/FluidMaterials.json @@ -8,7 +8,8 @@ }, "Variables" : { "DENSITY" : 1000.0, - "DYNAMIC_VISCOSITY" : 0.001002 + "DYNAMIC_VISCOSITY" : 0.001002, + "PERMEABILITY" : [[0,0,0],[0,0,0],[0,0,0]] }, "Tables" : {} } diff --git a/applications/SwimmingDEMApplication/tests/porosity_tests/porosity_conservation/ProjectParameters.json b/applications/SwimmingDEMApplication/tests/porosity_tests/porosity_conservation/ProjectParameters.json index 9dbd82139414..cd08247b6065 100644 --- a/applications/SwimmingDEMApplication/tests/porosity_tests/porosity_conservation/ProjectParameters.json +++ b/applications/SwimmingDEMApplication/tests/porosity_tests/porosity_conservation/ProjectParameters.json @@ -313,7 +313,7 @@ }, "echo_level" : 0, "compute_reactions" : false, - "maximum_iterations" : 10, + "maximum_iterations" : 1, "relative_velocity_tolerance" : 0.001, "absolute_velocity_tolerance" : 1e-5, "relative_pressure_tolerance" : 0.001,