fix(poly): bug fixing in block form

currently derivitive constraint is not working
This commit is contained in:
2025-04-03 11:14:50 -04:00
parent dcc4381cbb
commit acf5367556
10 changed files with 112 additions and 261 deletions

View File

@@ -34,6 +34,8 @@
#include "resourceManagerTypes.h"
#include "operator.h"
#include "debug.h"
#include "quill/LogMacros.h"
@@ -149,14 +151,14 @@ void PolySolver::assembleBlockSystem() {
// A full derivation of the weak form can be found in the 4DSSE documentation
// --- Assemble the MixedBilinear and Bilinear forms (M, D, and Q) ---
auto Mform = std::make_unique<mfem::MixedBilinearForm>(m_feTheta.get(), m_fePhi.get());
auto Qform = std::make_unique<mfem::MixedBilinearForm>(m_fePhi.get(), m_feTheta.get());
auto Mform = std::make_unique<mfem::MixedBilinearForm>(m_fePhi.get(), m_feTheta.get());
auto Qform = std::make_unique<mfem::MixedBilinearForm>(m_feTheta.get(), m_fePhi.get());
auto Dform = std::make_unique<mfem::BilinearForm>(m_fePhi.get());
// TODO: Check the sign on all of the integrators
Mform->AddDomainIntegrator(new mfem::MixedVectorWeakDivergenceIntegrator(negOneCoeff));
Qform->AddDomainIntegrator(new mfem::MixedVectorGradientIntegrator(negOneVCoeff));
Dform->AddDomainIntegrator(new mfem::VectorFEMassIntegrator(oneCoeff));
Mform->AddDomainIntegrator(new mfem::MixedVectorWeakDivergenceIntegrator());
Qform->AddDomainIntegrator(new mfem::MixedVectorGradientIntegrator());
Dform->AddDomainIntegrator(new mfem::VectorFEMassIntegrator());
Mform->Assemble();
Mform->Finalize();
@@ -187,47 +189,24 @@ void PolySolver::solve(){
// --- Set the initial guess for the solution ---
setInitialGuess();
// --- Set the essential true dofs for the operator ---
mfem::Array<int> theta_ess_tdof_list, phi_ess_tdof_list;
std::tie(theta_ess_tdof_list, phi_ess_tdof_list) = getEssentialTrueDof();
m_polytropOperator->SetEssentialTrueDofs(theta_ess_tdof_list, phi_ess_tdof_list);
setupOperator();
// --- Load configuration parameters ---
double newtonRelTol = m_config.get<double>("Poly:Solver:Newton:RelTol", 1e-7);
double newtonAbsTol = m_config.get<double>("Poly:Solver:Newton:AbsTol", 1e-7);
int newtonMaxIter = m_config.get<int>("Poly:Solver:Newton:MaxIter", 200);
int newtonPrintLevel = m_config.get<int>("Poly:Solver:Newton:PrintLevel", 1);
// 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);
state_vector.GetBlock(0) = *m_theta;
state_vector.GetBlock(1) = *m_phi;
double gmresRelTol = m_config.get<double>("Poly:Solver:GMRES:RelTol", 1e-10);
double gmresAbsTol = m_config.get<double>("Poly:Solver:GMRES:AbsTol", 1e-12);
int gmresMaxIter = m_config.get<int>("Poly:Solver:GMRES:MaxIter", 2000);
int gmresPrintLevel = m_config.get<int>("Poly:Solver:GMRES:PrintLevel", 0);
mfem::Vector zero_rhs(block_offsets.Last());
zero_rhs = 0.0;
LOG_DEBUG(m_logger, "Newton Solver (relTol: {:0.2E}, absTol: {:0.2E}, maxIter: {}, printLevel: {})", newtonRelTol, newtonAbsTol, newtonMaxIter, newtonPrintLevel);
LOG_DEBUG(m_logger, "GMRES Solver (relTol: {:0.2E}, absTol: {:0.2E}, maxIter: {}, printLevel: {})", gmresRelTol, gmresAbsTol, gmresMaxIter, gmresPrintLevel);
// --- Set up the Newton solver ---
mfem::NewtonSolver newtonSolver;
newtonSolver.SetRelTol(newtonRelTol);
newtonSolver.SetAbsTol(newtonAbsTol);
newtonSolver.SetMaxIter(newtonMaxIter);
newtonSolver.SetPrintLevel(newtonPrintLevel);
newtonSolver.SetOperator(*m_polytropOperator);
mfem::GMRESSolver gmresSolver;
gmresSolver.SetRelTol(gmresRelTol);
gmresSolver.SetAbsTol(gmresAbsTol);
gmresSolver.SetMaxIter(gmresMaxIter);
gmresSolver.SetPrintLevel(gmresPrintLevel);
newtonSolver.SetSolver(gmresSolver);
// newtonSolver.SetAdaptiveLinRtol();
mfem::NewtonSolver newtonSolver = setupNewtonSolver();
mfem::Vector B(m_feTheta->GetTrueVSize());
B = 0.0;
newtonSolver.Mult(B, *m_theta);
newtonSolver.Mult(zero_rhs, state_vector);
// --- Save and view the solution ---
saveAndViewSolution();
saveAndViewSolution(state_vector);
}
@@ -295,22 +274,77 @@ void PolySolver::setInitialGuess() {
}
void PolySolver::saveAndViewSolution() {
void PolySolver::saveAndViewSolution(const mfem::BlockVector& state_vector) {
mfem::BlockVector x_block(const_cast<mfem::BlockVector&>(state_vector), m_polytropOperator->GetBlockOffsets());
mfem::Vector& x_theta = x_block.GetBlock(0);
mfem::Vector& x_phi = x_block.GetBlock(1);
bool doView = m_config.get<bool>("Poly:Output:View", false);
if (doView) {
Probe::glVisView(*m_theta, *m_mesh, "solution");
Probe::glVisView(x_theta, *m_feTheta, "θ Solution");
Probe::glVisView(x_phi, *m_fePhi, "ɸ Solution");
}
// --- Extract the Solution ---
bool write11DSolution = m_config.get<bool>("Poly:Output:1D:Save", true);
if (write11DSolution) {
std::string solutionPath = m_config.get<std::string>("Poly:Output:1D:Path", "polytropeSolution_1D.csv");
std::string derivSolPath = "d" + solutionPath;
double rayCoLatitude = m_config.get<double>("Poly:Output:1D:RayCoLatitude", 0.0);
double rayLongitude = m_config.get<double>("Poly:Output:1D:RayLongitude", 0.0);
int raySamples = m_config.get<int>("Poly:Output:1D:RaySamples", 100);
std::vector rayDirection = {rayCoLatitude, rayLongitude};
Probe::getRaySolution(*m_theta, *m_feTheta, rayDirection, raySamples, solutionPath);
Probe::getRaySolution(x_theta, *m_feTheta, rayDirection, raySamples, solutionPath);
// Probe::getRaySolution(x_phi, *m_fePhi, rayDirection, raySamples, derivSolPath);
}
}
void PolySolver::setupOperator() {
mfem::Array<int> theta_ess_tdof_list, phi_ess_tdof_list;
std::tie(theta_ess_tdof_list, phi_ess_tdof_list) = getEssentialTrueDof();
m_polytropOperator->SetEssentialTrueDofs(theta_ess_tdof_list, phi_ess_tdof_list);
// -- Finalize the operator --
m_polytropOperator->finalize();
if (!m_polytropOperator->isFinalized()) {
LOG_ERROR(m_logger, "PolytropeOperator is not finalized. Cannot solve.");
throw std::runtime_error("PolytropeOperator is not finalized. Cannot solve.");
}
}
mfem::NewtonSolver PolySolver::setupNewtonSolver(){
// --- Load configuration parameters ---
double newtonRelTol = m_config.get<double>("Poly:Solver:Newton:RelTol", 1e-7);
double newtonAbsTol = m_config.get<double>("Poly:Solver:Newton:AbsTol", 1e-7);
int newtonMaxIter = m_config.get<int>("Poly:Solver:Newton:MaxIter", 200);
int newtonPrintLevel = m_config.get<int>("Poly:Solver:Newton:PrintLevel", 1);
double gmresRelTol = m_config.get<double>("Poly:Solver:GMRES:RelTol", 1e-10);
double gmresAbsTol = m_config.get<double>("Poly:Solver:GMRES:AbsTol", 1e-12);
int gmresMaxIter = m_config.get<int>("Poly:Solver:GMRES:MaxIter", 2000);
int gmresPrintLevel = m_config.get<int>("Poly:Solver:GMRES:PrintLevel", 0);
LOG_DEBUG(m_logger, "Newton Solver (relTol: {:0.2E}, absTol: {:0.2E}, maxIter: {}, printLevel: {})", newtonRelTol, newtonAbsTol, newtonMaxIter, newtonPrintLevel);
LOG_DEBUG(m_logger, "GMRES Solver (relTol: {:0.2E}, absTol: {:0.2E}, maxIter: {}, printLevel: {})", gmresRelTol, gmresAbsTol, gmresMaxIter, gmresPrintLevel);
// --- Set up the Newton solver ---
mfem::NewtonSolver newtonSolver;
newtonSolver.SetRelTol(newtonRelTol);
newtonSolver.SetAbsTol(newtonAbsTol);
newtonSolver.SetMaxIter(newtonMaxIter);
newtonSolver.SetPrintLevel(newtonPrintLevel);
newtonSolver.SetOperator(*m_polytropOperator);
mfem::GMRESSolver gmresSolver;
gmresSolver.SetRelTol(gmresRelTol);
gmresSolver.SetAbsTol(gmresAbsTol);
gmresSolver.SetMaxIter(gmresMaxIter);
gmresSolver.SetPrintLevel(gmresPrintLevel);
newtonSolver.SetSolver(gmresSolver);
// newtonSolver.SetAdaptiveLinRtol();
return newtonSolver;
}