Center of the Bubble
scalar totalBubbleVolume = 0.0;
vector weightedPosition(vector::zero);
forAll(alpha1, cellI)
{
if (alpha1[cellI] > 0.5) // Assuming alpha1 represents the bubble phase
{
totalBubbleVolume += mesh.V()[cellI];
weightedPosition += mesh.V()[cellI] * mesh.C()[cellI];
}
}
reduce(totalBubbleVolume, sumOp<scalar>());
reduce(weightedPosition, sumOp<vector>());
if (totalBubbleVolume > SMALL) // prevents div. by 0 error. SMALL in OpenFOAM is defined as 1e-15. ()
{
Cb = weightedPosition / totalBubbleVolume;
}
Info<< "Updated bubble center: " << Cb << endl;
Write Cb as a Field (to visualize it in paraview)
volScalarField CbField
(
IOobject
(
"CbField",
runTime.timeName(),
mesh,
IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE
),
mesh,
dimensionedScalar("zero", dimless, 0.0)
);
{
// Reset CbField to zero
CbField = dimensionedScalar("zero", dimless, 0.0);
// Find the cell containing Cb
label cellId = mesh.findCell(Cb);
if (cellId >= 0)
{
// Set the value to 1 in the cell containing Cb
CbField[cellId] = 1.0;
}
// Correct boundary conditions
CbField.correctBoundaryConditions();
Info<< "Cb field updated. Center at cell: " << cellId << endl;
}
Domain Center
scalar totalVolume = gSum(mesh.V());
// Weighted sum of cell centers
vector volumeWeightedSum = vector::zero;
forAll(mesh.C(), cellI)
{
volumeWeightedSum += mesh.C()[cellI] * mesh.V()[cellI];
}
reduce(volumeWeightedSum, sumOp<vector>());
vector domainCenter = volumeWeightedSum / totalVolume;
Info << "Domain center: " << domainCenter << endl;
Bubble Velocity
vector Cbf(0, 0, 0); // Target/initial bubble center position
vector Cb0 = Cb; // Previous time step bubble center position
vector UF(0, 0, 0); // Initial bubble velocity
vector XF = Cb; // Initial bubble position
// at the moment the target and the initial are the same
// Hardcoded parameters
scalar lambdaFf = 1.0;
scalar lambdaF0 = 1.0;
// Calculate change in velocity (bubble displacement / time)
vector dUF = lambdaFf * (Cb - Cbf) / runTime.deltaT().value()
+ lambdaF0 * (Cb - Cb0) / runTime.deltaT().value();
Here,
- Long-term tracking
- Ensures that the bubble tends towards its initial position over time.
- If the bubble has moved far from its initial position, this term will be larger, creating a stronger “restoring” velocity.
- Short-term adjustment (second term):
- This term accounts for recent changes in the bubble’s position.
- It allows the model to respond to rapid changes or perturbations in the bubble’s motion.
dimensionedVector dimUF("UF", dimVelocity, UF);
dimensionedVector dimDUF("dUF", dimVelocity, dUF);
dimensionedVector dimXF("XF", dimLength, XF);
This ensures that the variables are stored along with their dimensions.
Updating Bubble Position (Verlet Algorithm)
dimXF += (dimUF + 0.5 * dimDUF) * runTime.deltaT();
XF = dimXF.value(); // Convert back to vector
Given:
- Initial velocity:
- Velocity change:
- Final velocity:
We assume constant acceleration over the time step. In this case, the average velocity is the arithmetic mean of the initial and final velocities:
Substituting the expressions for and :