fix(poly): phi boundary values now coorespond to theta flux through polytrope surface
This commit is contained in:
@@ -139,7 +139,7 @@ std::unique_ptr<formBundle> PolySolver::buildIndividualForms(const mfem::Array<i
|
||||
);
|
||||
|
||||
// --- -M negation -> M ---
|
||||
mfem::Vector negOneVec(m_fePhi->GetVDim());
|
||||
mfem::Vector negOneVec(m_mesh->SpaceDimension());
|
||||
negOneVec = -1.0;
|
||||
|
||||
m_negationCoeff = std::make_unique<mfem::VectorConstantCoefficient>(negOneVec);
|
||||
@@ -184,9 +184,6 @@ void PolySolver::solve() const {
|
||||
throw std::runtime_error("PolytropeOperator is not finalized. Cannot solve.");
|
||||
}
|
||||
|
||||
GetDofCoordinates(*m_feTheta, "dof2posTheta.csv");
|
||||
GetDofCoordinates(*m_fePhi, "dof2posPhi.csv");
|
||||
|
||||
// It's safer to get the offsets directly from the operator after finalization
|
||||
const mfem::Array<int>& block_offsets = m_polytropOperator->GetBlockOffsets(); // Assuming a getter exists or accessing member if public/friend
|
||||
mfem::BlockVector state_vector(block_offsets);
|
||||
@@ -194,23 +191,14 @@ void PolySolver::solve() const {
|
||||
state_vector.GetBlock(1) = phiVec; // NOLINT(*-slicing)
|
||||
|
||||
|
||||
mfem::Vector zero_rhs(block_offsets.Last());
|
||||
mfem::Vector zero_rhs(block_offsets.Last()); // TODO: Is this right?
|
||||
zero_rhs = 0.0;
|
||||
|
||||
const solverBundle sb = setupNewtonSolver();
|
||||
|
||||
// EMB 2025: Calling Mult gets the gradient of the operator for the NewtonSolver
|
||||
// This then is set as the operator for the solver for NewtonSolver
|
||||
// The solver (assuming it is an iterative solver) then sets the
|
||||
// operator for its preconditioner to this.
|
||||
// What this means is that there is no need to manually deal
|
||||
// with updating the preconditioner at every newton step as the
|
||||
// changes to the jacobian are automatically propagated through the
|
||||
// solving chain. This is at least true with MFEM 4.8-rc0
|
||||
std::string windowTitle = "testWindow";
|
||||
std::string keyset = "";
|
||||
sb.newton.Mult(zero_rhs, state_vector);
|
||||
|
||||
// Ax = b for x
|
||||
|
||||
// --- Save and view the solution ---
|
||||
saveAndViewSolution(state_vector);
|
||||
}
|
||||
@@ -219,28 +207,31 @@ SSE::MFEMArrayPairSet PolySolver::getEssentialTrueDof() const {
|
||||
mfem::Array<int> theta_ess_tdof_list;
|
||||
mfem::Array<int> phi_ess_tdof_list;
|
||||
|
||||
mfem::Array<int> thetaCenterDofs, phiCenterDofs;
|
||||
mfem::Array<double> thetaCenterVals, phiCenterVals;
|
||||
std::tie(thetaCenterDofs, phi_ess_tdof_list) = findCenterElement();
|
||||
mfem::Array<int> thetaCenterDofs, phiCenterDofs; // phiCenterDofs are not used
|
||||
mfem::Array<double> thetaCenterVals;
|
||||
std::tie(thetaCenterDofs, phiCenterDofs) = findCenterElement();
|
||||
thetaCenterVals.SetSize(thetaCenterDofs.Size());
|
||||
phiCenterVals.SetSize(phi_ess_tdof_list.Size());
|
||||
|
||||
thetaCenterVals = 1.0;
|
||||
phiCenterVals = 0.0;
|
||||
|
||||
mfem::Array<int> ess_brd(m_mesh->bdr_attributes.Max());
|
||||
ess_brd = 1;
|
||||
|
||||
mfem::Array<double> thetaSurfaceVals;
|
||||
mfem::Array<double> thetaSurfaceVals, phiSurfaceVals;
|
||||
m_feTheta->GetEssentialTrueDofs(ess_brd, theta_ess_tdof_list);
|
||||
m_fePhi->GetEssentialTrueDofs(ess_brd, phi_ess_tdof_list);
|
||||
|
||||
thetaSurfaceVals.SetSize(theta_ess_tdof_list.Size());
|
||||
thetaSurfaceVals = 0.0;
|
||||
phiSurfaceVals.SetSize(phi_ess_tdof_list.Size());
|
||||
phiSurfaceVals = polycoeff::thetaSurfaceFlux(m_polytropicIndex);
|
||||
|
||||
// combine the essential dofs with the center dofs
|
||||
theta_ess_tdof_list.Append(thetaCenterDofs);
|
||||
thetaSurfaceVals.Append(thetaCenterVals);
|
||||
|
||||
SSE::MFEMArrayPair thetaPair = std::make_pair(theta_ess_tdof_list, thetaSurfaceVals);
|
||||
SSE::MFEMArrayPair phiPair = std::make_pair(phi_ess_tdof_list, phiCenterVals);
|
||||
SSE::MFEMArrayPair phiPair = std::make_pair(phi_ess_tdof_list, phiSurfaceVals);
|
||||
SSE::MFEMArrayPairSet pairSet = std::make_pair(thetaPair, phiPair);
|
||||
|
||||
return pairSet;
|
||||
@@ -275,16 +266,39 @@ void PolySolver::setInitialGuess() const {
|
||||
const double radius = Probe::getMeshRadius(*m_mesh);
|
||||
const double u = 1/radius;
|
||||
|
||||
return (-1.0/radius) * r + 1;
|
||||
// return (-1.0/radius) * r + 1;
|
||||
// return -std::pow((u*r), 2)+1.0; // The series expansion is a better guess; however, this is cheaper and ensures that the value at the surface is very close to zero in a way that the series expansion does not
|
||||
return laneEmden::thetaSeriesExpansion(r, m_polytropicIndex, 5);
|
||||
}
|
||||
);
|
||||
|
||||
mfem::VectorFunctionCoefficient phiSurfaceVectors (m_mesh->SpaceDimension(),
|
||||
[this](const mfem::Vector &x, mfem::Vector &y) {
|
||||
const double r = x.Norml2();
|
||||
mfem::Vector xh(x);
|
||||
xh /= r; // Normalize the vector
|
||||
y.SetSize(m_mesh->SpaceDimension());
|
||||
y = xh;
|
||||
y *= polycoeff::thetaSurfaceFlux(m_polytropicIndex);
|
||||
}
|
||||
);
|
||||
// We want to apply specific boundary conditions to the surface
|
||||
mfem::Array<int> ess_brd(m_mesh->bdr_attributes.Max());
|
||||
ess_brd = 1;
|
||||
|
||||
// θ = 0 at surface
|
||||
mfem::ConstantCoefficient surfacePotential(0);
|
||||
|
||||
m_theta->ProjectCoefficient(thetaInitGuess);
|
||||
m_theta->ProjectBdrCoefficient(surfacePotential, ess_brd);
|
||||
|
||||
mfem::GradientGridFunctionCoefficient phiInitGuess (m_theta.get());
|
||||
m_phi->ProjectCoefficient(phiInitGuess);
|
||||
m_phi->ProjectBdrCoefficientNormal(phiSurfaceVectors, ess_brd);
|
||||
|
||||
if (m_config.get<bool>("Poly:Solver:ViewInitialGuess", false)) {
|
||||
Probe::glVisView(*m_theta, *m_mesh, "θ init");
|
||||
Probe::glVisView(*m_phi, *m_mesh, "ɸ init");
|
||||
Probe::glVisView(*m_phi, *m_mesh, "φ init");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -335,7 +349,7 @@ void PolySolver::LoadSolverUserParams(double &newtonRelTol, double &newtonAbsTol
|
||||
LOG_DEBUG(m_logger, "GMRES Solver (relTol: {:0.2E}, absTol: {:0.2E}, maxIter: {}, printLevel: {})", gmresRelTol, gmresAbsTol, gmresMaxIter, gmresPrintLevel);
|
||||
}
|
||||
|
||||
void PolySolver::GetDofCoordinates(mfem::FiniteElementSpace &fes, const std::string& filename) const {
|
||||
void PolySolver::GetDofCoordinates(const mfem::FiniteElementSpace &fes, const std::string& filename) {
|
||||
mfem::Mesh *mesh = fes.GetMesh();
|
||||
double r = Probe::getMeshRadius(*mesh);
|
||||
std::ofstream outputFile(filename, std::ios::out | std::ios::trunc);
|
||||
|
||||
Reference in New Issue
Block a user