diff --git a/docs/sphinx/changelog.rst b/docs/sphinx/changelog.rst index ed940fd..4d34f94 100644 --- a/docs/sphinx/changelog.rst +++ b/docs/sphinx/changelog.rst @@ -12,6 +12,7 @@ Changelog New Features ============ - Added iterator based calculation of the balance of mass (:pull:`9`). By `Nathan Miller`_. +- Added a multiphase balance of mass calculation (:pull:`10`). By `Nathan Miller`_. ****************** 0.1.0 (11-07-2024) diff --git a/src/cpp/tardigrade_balance_of_mass.cpp b/src/cpp/tardigrade_balance_of_mass.cpp index fa9e6ed..0e728b7 100644 --- a/src/cpp/tardigrade_balance_of_mass.cpp +++ b/src/cpp/tardigrade_balance_of_mass.cpp @@ -160,6 +160,106 @@ namespace tardigradeBalanceEquations{ } + template + void computeBalanceOfMass( const scalarArray_iter &density_begin, const scalarArray_iter &density_end, + const scalarArray_iter &density_dot_begin, const scalarArray_iter &density_dot_end, + const floatVectorArray_iter &density_gradient_begin, const floatVectorArray_iter &density_gradient_end, + const floatVectorArray_iter &velocity_begin, const floatVectorArray_iter &velocity_end, + const secondOrderTensorArray_iter &velocity_gradient_begin, const secondOrderTensorArray_iter &velocity_gradient_end, + scalarArray_iter_out mass_change_rate_begin, scalarArray_iter_out mass_change_rate_end ){ + /*! + * Compute the balance of mass for a multi-phase continuum returning the values of the mass-change rate + * + * \f$ \frac{\partial \rho}{\partial t} + \left( \rho v_i \right)_{,i} = c \f$ + * + * \param &density_begin: The starting point of the density \f$ \rho \f$ + * \param &density_end: The stopping point of the density \f$ \rho \f$ + * \param &density_dot_begin: The starting point of the partial time derivative of the density \f$ \frac{\partial \rho}{\partial t} \f$ + * \param &density_dot_end: The stopping point of the partial time derivative of the density \f$ \frac{\partial \rho}{\partial t} \f$ + * \param &density_gradient_begin: The starting point of the spatial gradient of the density \f$ \rho_{,i} \f$ + * \param &density_gradient_end: The stopping point of the spatial gradient of the density \f$ \rho_{,i} \f$ + * \param &velocity_begin: The starting point of the velocity \f$ v_i \f$ + * \param &velocity_end: The stopping point of the velocity \f$ v_i \f$ + * \param &velocity_gradient_begin: The starting point of the spatial gradient of the velocity \f$ v_{i,j} \f$ + * \param &velocity_gradient_end: The stopping point of the spatial gradient of the velocity \f$ v_{i,j} \f$ + * \param &mass_change_rate_begin: The starting point of the rate of change of the mass \f$ c \f$ + * \param &mass_change_rate_end: The stopping point of the rate of change of the mass \f$ c \f$ + */ + + unsigned int phase; + + for ( auto rho = density_begin; rho != density_end; rho++ ){ + + phase = ( unsigned int )( rho - density_begin ); + + computeBalanceOfMass( *( density_begin + phase ), *( density_dot_begin + phase ), + density_gradient_begin + dim * phase, density_gradient_begin + dim * ( phase + 1 ), + velocity_begin + dim * phase, velocity_begin + dim * ( phase + 1 ), + velocity_gradient_begin + sot_dim * phase, velocity_gradient_begin + sot_dim * ( phase + 1 ), + *( mass_change_rate_begin + phase ) ); + + } + + } + + template + void computeBalanceOfMass( const scalarArray_iter &density_begin, const scalarArray_iter &density_end, + const scalarArray_iter &density_dot_begin, const scalarArray_iter &density_dot_end, + const floatVector_iter &density_gradient_begin, const floatVector_iter &density_gradient_end, + const floatVector_iter &velocity_begin, const floatVector_iter &velocity_end, + const secondOrderTensor_iter &velocity_gradient_begin, const secondOrderTensor_iter &velocity_gradient_end, + scalarArray_iter_out mass_change_rate_begin, scalarArray_iter_out mass_change_rate_end, + scalarArray_iter_out dCdRho_begin, scalarArray_iter_out dCdRho_end, + scalarArray_iter_out dCdRhoDot_begin, scalarArray_iter_out dCdRhoDot_end, + floatVector_iter_out dCdGradRho_begin, floatVector_iter_out dCdGradRho_end, + floatVector_iter_out dCdV_begin, floatVector_iter_out dCdV_end, + secondOrderTensor_iter_out dCdGradV_begin, secondOrderTensor_iter_out dCdGradV_end ){ + /*! + * Compute the value of the balance of mass returning the value of the mass change rate + * + * \f$ \frac{\partial \rho}{\partial t} + \left( \rho v_i \right)_{,i} = c \f$ + * + * \param &density: The value of the density \f$ \rho \f$ + * \param &density_dot: The value of the partial time derivative of the density \f$ \frac{\partial \rho}{\partial t} \f$ + * \param &density_gradient_begin: The starting point of the spatial gradient of the density \f$ \rho_{,i} \f$ + * \param &density_gradient_end: The stopping point of the spatial gradient of the density \f$ \rho_{,i} \f$ + * \param &velocity_begin: The starting point of the velocity \f$ v_i \f$ + * \param &velocity_end: The stopping point of the velocity \f$ v_i \f$ + * \param &velocity_gradient_begin: The starting point of the spatial gradient of the velocity \f$ v_{i,j} \f$ + * \param &velocity_gradient_end: The stopping point of the spatial gradient of the velocity \f$ v_{i,j} \f$ + * \param &mass_change_rate_begin: The starting point of the rate of change of the mass \f$ c \f$ + * \param &mass_change_rate_end: The stopping point of the rate of change of the mass \f$ c \f$ + * \param &dCdRho_begin: The starting point of the derivative of the mass change rate w.r.t. density \f$ \rho \f$ + * \param &dCdRho_end: The stopping point of the derivative of the mass change rate w.r.t. density \f$ \rho \f$ + * \param &dCdRhoDot_begin: The starting point of the derivative of the mass change rate w.r.t. partial time derivative of the density \f$ \frac{\partial \rho}{\partial t} \f$ + * \param &dCdRhoDot_end: The stopping point of the derivative of the mass change rate w.r.t. partial time derivative of the density \f$ \frac{\partial \rho}{\partial t} \f$ + * \param &dCdGradRho_begin: The starting point of the derivative of the mass change rate w.r.t. the spatial gradient of the density \f$ \rho_{,i} \f$ + * \param &dCdGradRho_end: The stopping point of the derivative of the mass change rate w.r.t. the spatial gradient of the density \f$ \rho_{,i} \f$ + * \param &dCdV_begin: The starting point of the derivative of the mass change rate w.r.t. the velocity \f$ v_{i} \f$ + * \param &dCdV_end: The stopping point of the derivative of the mass change rate w.r.t. the velocity \f$ v_{i} \f$ + * \param &dCdGradV_begin: The starting point of the derivative of the mass change rate w.r.t. the spatial gradient of the velocity \f$ v_{i,j} \f$ + * \param &dCdGradV_end: The stopping point of the derivative of the mass change rate w.r.t. the spatial gradient of the velocity \f$ v_{i,j} \f$ + */ + + unsigned int phase; + + for ( auto rho = density_begin; rho != density_end; rho++ ){ + + phase = ( unsigned int )( rho - density_begin ); + + computeBalanceOfMass( *( density_begin + phase ), *( density_dot_begin + phase ), + density_gradient_begin + dim * phase, density_gradient_begin + dim * ( phase + 1 ), + velocity_begin + dim * phase, velocity_begin + dim * ( phase + 1 ), + velocity_gradient_begin + sot_dim * phase, velocity_gradient_begin + sot_dim * ( phase + 1 ), + *( mass_change_rate_begin + phase ), *( dCdRho_begin + phase ), *( dCdRhoDot_begin + phase ), + dCdGradRho_begin + dim * phase, dCdGradRho_begin + dim * ( phase + 1 ), + dCdV_begin + dim * phase, dCdV_begin + dim * ( phase + 1 ), + dCdGradV_begin + sot_dim * phase, dCdGradV_begin + sot_dim * ( phase + 1 ) ); + + } + + } + } } diff --git a/src/cpp/tardigrade_balance_of_mass.h b/src/cpp/tardigrade_balance_of_mass.h index 005a915..729829a 100644 --- a/src/cpp/tardigrade_balance_of_mass.h +++ b/src/cpp/tardigrade_balance_of_mass.h @@ -53,6 +53,27 @@ namespace tardigradeBalanceEquations{ floatVector_iter_out dCdV_begin, floatVector_iter_out dCdV_end, secondOrderTensor_iter_out dCdGradV_begin, secondOrderTensor_iter_out dCdGradV_end ); + template + void computeBalanceOfMass( const scalarArray_iter &density_begin, const scalarArray_iter &density_end, + const scalarArray_iter &density_dot_begin, const scalarArray_iter &density_dot_end, + const floatVectorArray_iter &density_gradient_begin, const floatVectorArray_iter &density_gradient_end, + const floatVectorArray_iter &velocity_begin, const floatVectorArray_iter &velocity_end, + const floatVectorArray_iter &velocity_gradient_begin, const floatVectorArray_iter &velocity_gradient_end, + scalarArray_iter_out mass_change_rate_start, scalarArray_iter_out mass_change_rate_stop ); + + template + void computeBalanceOfMass( const scalarArray_iter &density_begin, const scalarArray_iter &density_end, + const scalarArray_iter &density_dot_begin, const scalarArray_iter &density_dot_end, + const floatVector_iter &density_gradient_begin, const floatVector_iter &density_gradient_end, + const floatVector_iter &velocity_begin, const floatVector_iter &velocity_end, + const secondOrderTensor_iter &velocity_gradient_begin, const secondOrderTensor_iter &velocity_gradient_end, + scalarArray_iter_out mass_change_rate_begin, scalarArray_iter_out mass_change_rate_end, + scalarArray_iter_out dCdRho_begin, scalarArray_iter_out dCdRho_end, + scalarArray_iter_out dCdRhoDot_begin, scalarArray_iter_out dCdRhoDot_end, + floatVector_iter_out dCdGradRho_begin, floatVector_iter_out dCdGradRho_end, + floatVector_iter_out dCdV_begin, floatVector_iter_out dCdV_end, + secondOrderTensor_iter_out dCdGradV_begin, secondOrderTensor_iter_out dCdGradV_end ); + } } diff --git a/src/cpp/tests/test_tardigrade_balance_of_mass.cpp b/src/cpp/tests/test_tardigrade_balance_of_mass.cpp index 2704f7b..80e3a49 100644 --- a/src/cpp/tests/test_tardigrade_balance_of_mass.cpp +++ b/src/cpp/tests/test_tardigrade_balance_of_mass.cpp @@ -202,3 +202,262 @@ BOOST_AUTO_TEST_CASE( test_computeBalanceOfMass, * boost::unit_test::tolerance( } } + +BOOST_AUTO_TEST_CASE( test_multiphase_computeBalanceOfMass, * boost::unit_test::tolerance( DEFAULT_TEST_TOLERANCE ) ){ + /*! + * Test computing the balance of mass + */ + + constexpr unsigned int nphases = 5; + constexpr unsigned int dim = 3; + + std::array density = { 0.44775226, 0.10257244, 0.02078009, 0.34655081, 0.63241094 }; + + std::array density_dot = { 0.21140475, 0.84172361, 0.90589625, 0.65667824, 0.12870103 }; + + std::array density_gradient = { 0.84973079, 0.69994479, 0.19507225, 0.71997378, 0.40400888, + 0.10209729, 0.45538381, 0.78085324, 0.38934166, 0.80650313, + 0.37377701, 0.52589524, 0.21972558, 0.6619266 , 0.71868273 }; + + std::array velocity = { 1.78845045e-01, 3.43184239e-04, 3.03570624e-01, 2.61149246e-01, + 6.22089112e-01, 4.77309376e-01, 2.83884563e-01, 8.54215703e-01, + 6.62676921e-01, 1.26475940e-01, 7.91005742e-01, 6.58327605e-01, + 9.64615247e-01, 5.82284188e-01, 8.29503047e-01 }; + + std::array velocity_gradient = { 0.08057272, 0.30451766, 0.56826345, 0.23438303, 0.61955306, + 0.44571224, 0.15461077, 0.98556686, 0.01420748, 0.41255824, + 0.1579279 , 0.98449085, 0.57013379, 0.15921173, 0.96501503, + 0.15371508, 0.64557532, 0.08269366, 0.98004204, 0.59460498, + 0.68023366, 0.88135227, 0.68412015, 0.51093195, 0.35998666, + 0.62551418, 0.90176422, 0.15462472, 0.90648864, 0.51429834, + 0.65717033, 0.29536049, 0.57881457, 0.58403957, 0.12585209, + 0.99548878, 0.1307144 , 0.92037728, 0.54106702, 0.43851027, + 0.73620888, 0.66502109, 0.64664504, 0.8294774 , 0.9394895 }; + + std::array answer = { 0.74267764, 1.39693567, 2.01351769, 1.90148278, 2.46462579 }; + + std::array result; + + tardigradeBalanceEquations::balanceOfMass::computeBalanceOfMass( std::begin( density ), std::end( density ), std::begin( density_dot ), std::end( density_dot ), + std::begin( density_gradient ), std::end( density_gradient ), std::begin( velocity ), std::end( velocity ), + std::begin( velocity_gradient ), std::end( velocity_gradient ), std::begin( result ), std::end( result ) ); + + BOOST_TEST( answer == result, CHECK_PER_ELEMENT ); + + std::array dCdRho, dCdRhoDot; + + std::array dCdGradRho, dCdV; + + std::array dCdGradV; + + tardigradeBalanceEquations::balanceOfMass::computeBalanceOfMass( std::begin( density ), std::end( density ), std::begin( density_dot ), std::end( density_dot ), + std::begin( density_gradient ), std::end( density_gradient ), std::begin( velocity ), std::end( velocity ), + std::begin( velocity_gradient ), std::end( velocity_gradient ), std::begin( result ), std::end( result ), + std::begin( dCdRho ), std::end( dCdRho ), + std::begin( dCdRhoDot ), std::end( dCdRhoDot ), + std::begin( dCdGradRho ), std::end( dCdGradRho ), + std::begin( dCdV ), std::end( dCdV ), + std::begin( dCdGradV ), std::end( dCdGradV ) ); + + BOOST_TEST( answer == result, CHECK_PER_ELEMENT ); + + floatType eps = 1e-6; + + // Derivative w.r.t. density + for ( unsigned int i = 0; i < nphases; i++ ){ + + floatType delta = eps * std::fabs( density[ i ] ) + eps; + + std::array xp = density; + + std::array xm = density; + + xp[ i ] += delta; + xm[ i ] -= delta; + + std::array vp, vm; + + tardigradeBalanceEquations::balanceOfMass::computeBalanceOfMass( std::begin( xp ), std::end( xp ), std::begin( density_dot ), std::end( density_dot ), + std::begin( density_gradient ), std::end( density_gradient ), std::begin( velocity ), std::end( velocity ), + std::begin( velocity_gradient ), std::end( velocity_gradient ), std::begin( vp ), std::end( vp ) ); + + tardigradeBalanceEquations::balanceOfMass::computeBalanceOfMass( std::begin( xm ), std::end( xm ), std::begin( density_dot ), std::end( density_dot ), + std::begin( density_gradient ), std::end( density_gradient ), std::begin( velocity ), std::end( velocity ), + std::begin( velocity_gradient ), std::end( velocity_gradient ), std::begin( vm ), std::end( vm ) ); + + for ( unsigned int j = 0; j < nphases; j++ ){ + + floatType grad = ( vp[ j ] - vm[ j ] ) / ( 2 * delta ); + + if ( j == i ){ + BOOST_TEST( dCdRho[ i ] == grad ); + } + else{ + BOOST_TEST( grad == 0 ); + } + + } + + } + + // Derivative w.r.t. density dot + for ( unsigned int i = 0; i < nphases; i++ ){ + + floatType delta = eps * std::fabs( density_dot[ i ] ) + eps; + + std::array xp = density_dot; + + std::array xm = density_dot; + + xp[ i ] += delta; + xm[ i ] -= delta; + + std::array vp, vm; + + tardigradeBalanceEquations::balanceOfMass::computeBalanceOfMass( std::begin( density ), std::end( density ), std::begin( xp ), std::end( xp ), + std::begin( density_gradient ), std::end( density_gradient ), std::begin( velocity ), std::end( velocity ), + std::begin( velocity_gradient ), std::end( velocity_gradient ), std::begin( vp ), std::end( vp ) ); + + tardigradeBalanceEquations::balanceOfMass::computeBalanceOfMass( std::begin( density ), std::end( density ), std::begin( xm ), std::end( xm ), + std::begin( density_gradient ), std::end( density_gradient ), std::begin( velocity ), std::end( velocity ), + std::begin( velocity_gradient ), std::end( velocity_gradient ), std::begin( vm ), std::end( vm ) ); + + for ( unsigned int j = 0; j < nphases; j++ ){ + + floatType grad = ( vp[ j ] - vm[ j ] ) / ( 2 * delta ); + + if ( j == i ){ + BOOST_TEST( dCdRhoDot[ i ] == grad ); + } + else{ + BOOST_TEST( grad == 0 ); + } + + } + + } + + // Derivative w.r.t. density gradient + for ( unsigned int i = 0; i < dim * nphases; i++ ){ + + floatType delta = eps * std::fabs( density_gradient[ i ] ) + eps; + + std::array xp = density_gradient; + + std::array xm = density_gradient; + + xp[ i ] += delta; + xm[ i ] -= delta; + + std::array vp, vm; + + tardigradeBalanceEquations::balanceOfMass::computeBalanceOfMass( std::begin( density ), std::end( density ), std::begin( density_dot ), std::end( density_dot ), + std::begin( xp ), std::end( xp ), std::begin( velocity ), std::end( velocity ), + std::begin( velocity_gradient ), std::end( velocity_gradient ), std::begin( vp ), std::end( vp ) ); + + tardigradeBalanceEquations::balanceOfMass::computeBalanceOfMass( std::begin( density ), std::end( density ), std::begin( density_dot ), std::end( density_dot ), + std::begin( xm ), std::end( xm ), std::begin( velocity ), std::end( velocity ), + std::begin( velocity_gradient ), std::end( velocity_gradient ), std::begin( vm ), std::end( vm ) ); + + for ( unsigned int j = 0; j < nphases; j++ ){ + + floatType grad = ( vp[ j ] - vm[ j ] ) / ( 2 * delta ); + + if ( ( unsigned int )( i / dim ) == j ){ + + BOOST_TEST( dCdGradRho[ i ] == grad ); + + } + else{ + + BOOST_TEST( grad == 0 ); + + } + + } + + } + + // Derivative w.r.t. velocity + for ( unsigned int i = 0; i < dim * nphases; i++ ){ + + floatType delta = eps * std::fabs( velocity[ i ] ) + eps; + + std::array xp = velocity; + + std::array xm = velocity; + + xp[ i ] += delta; + xm[ i ] -= delta; + + std::array vp, vm; + + tardigradeBalanceEquations::balanceOfMass::computeBalanceOfMass( std::begin( density ), std::end( density ), std::begin( density_dot ), std::end( density_dot ), + std::begin( density_gradient ), std::end( density_gradient ), std::begin( xp ), std::end( xp ), + std::begin( velocity_gradient ), std::end( velocity_gradient ), std::begin( vp ), std::end( vp ) ); + + tardigradeBalanceEquations::balanceOfMass::computeBalanceOfMass( std::begin( density ), std::end( density ), std::begin( density_dot ), std::end( density_dot ), + std::begin( density_gradient ), std::end( density_gradient ), std::begin( xm ), std::end( xm ), + std::begin( velocity_gradient ), std::end( velocity_gradient ), std::begin( vm ), std::end( vm ) ); + + for ( unsigned int j = 0; j < nphases; j++ ){ + + floatType grad = ( vp[ j ] - vm[ j ] ) / ( 2 * delta ); + + if ( ( unsigned int )( i / dim ) == j ){ + + BOOST_TEST( dCdV[ i ] == grad ); + + } + else{ + + BOOST_TEST( grad == 0 ); + + } + + } + + } + + // Derivative w.r.t. velocity gradient + for ( unsigned int i = 0; i < dim * dim * nphases; i++ ){ + + floatType delta = eps * std::fabs( velocity_gradient[ i ] ) + eps; + + std::array xp = velocity_gradient; + + std::array xm = velocity_gradient; + + xp[ i ] += delta; + xm[ i ] -= delta; + + std::array vp, vm; + + tardigradeBalanceEquations::balanceOfMass::computeBalanceOfMass( std::begin( density ), std::end( density ), std::begin( density_dot ), std::end( density_dot ), + std::begin( density_gradient ), std::end( density_gradient ), std::begin( velocity ), std::end( velocity ), + std::begin( xp ), std::end( xp ), std::begin( vp ), std::end( vp ) ); + + tardigradeBalanceEquations::balanceOfMass::computeBalanceOfMass( std::begin( density ), std::end( density ), std::begin( density_dot ), std::end( density_dot ), + std::begin( density_gradient ), std::end( density_gradient ), std::begin( velocity ), std::end( velocity ), + std::begin( xm ), std::end( xm ), std::begin( vm ), std::end( vm ) ); + + for ( unsigned int j = 0; j < nphases; j++ ){ + + floatType grad = ( vp[ j ] - vm[ j ] ) / ( 2 * delta ); + + if ( ( unsigned int )( i / ( dim * dim ) ) == j ){ + + BOOST_TEST( dCdGradV[ i ] == grad ); + + } + else{ + + BOOST_TEST( grad == 0 ); + + } + + } + + } + +}