@@ -66,6 +66,9 @@ void readRestartFiles(MGmolInterface *mgmol_)
6666 Control& ct = *(Control::instance ());
6767 Mesh* mymesh = Mesh::instance ();
6868 const pb::PEenv& myPEenv = mymesh->peenv ();
69+ MGmol_MPI& mmpi = *(MGmol_MPI::instance ());
70+ const int rank = mmpi.mypeGlobal ();
71+ const int nprocs = mmpi.size ();
6972
7073 ROMPrivateOptions rom_options = ct.getROMOptions ();
7174 /* type of variable we intend to run POD */
@@ -131,6 +134,9 @@ void readRestartFiles(MGmolInterface *mgmol_)
131134 /* we save hartree potential */
132135 basis_generator.takeSample (pot.vh_rho ());
133136 break ;
137+
138+ case ROMVariable::DENSITY:
139+ basis_prefix += " _density" ;
134140 }
135141 }
136142 basis_generator.writeSnapshot ();
@@ -202,11 +208,12 @@ void buildROMPoissonOperator(MGmolInterface *mgmol_)
202208 delete col;
203209 } // for (int c = 0; c < num_pot_basis; c++)
204210
205- /* DEIM hyperreduction */
211+ /* hyperreduction */
206212 CAROM::Matrix pot_rhs_rom (num_pot_basis, num_pot_basis, false );
207213 std::vector<int > global_sampled_row (num_pot_basis), sampled_rows_per_proc (nprocs);
208- DEIM (pot_basis, num_pot_basis, global_sampled_row, sampled_rows_per_proc,
209- pot_rhs_rom, rank, nprocs);
214+ CAROM::Hyperreduction HR (" deim" );
215+ HR.ComputeSamples (pot_basis, num_pot_basis, global_sampled_row, sampled_rows_per_proc,
216+ pot_rhs_rom, rank, nprocs, num_pot_basis);
210217 if (rank == 0 )
211218 {
212219 int num_sample_rows = 0 ;
@@ -276,6 +283,19 @@ void runPoissonROM(MGmolInterface *mgmol_)
276283 MPI_Abort (MPI_COMM_WORLD, 0 );
277284 }
278285
286+ /* Load MGmol pointer and Potentials */
287+ MGmol<OrbitalsType> *mgmol = static_cast <MGmol<OrbitalsType> *>(mgmol_);
288+ Poisson *poisson = mgmol->electrostat_ ->getPoissonSolver ();
289+ Potentials& pot = mgmol->getHamiltonian ()->potential ();
290+ std::shared_ptr<Rho<OrbitalsType>> rho = mgmol->getRho ();
291+ const int dim = pot.size ();
292+
293+ /* GridFunc initialization inputs */
294+ const pb::Grid &grid (poisson->vh ().grid ());
295+ short bc[3 ];
296+ for (int d = 0 ; d < 3 ; d++)
297+ bc[d] = poisson->vh ().bc (d);
298+
279299 /* Load Hartree potential basis matrix */
280300 std::string basis_file = rom_options.basis_file ;
281301 const int num_pot_basis = rom_options.num_potbasis ;
@@ -355,13 +375,6 @@ void runPoissonROM(MGmolInterface *mgmol_)
355375 int num_global_sample = CAROM::get_global_offsets (sampled_rows_per_proc[rank], offsets);
356376 for (int s = 0 , gs = offsets[rank]; gs < offsets[rank+1 ]; gs++, s++)
357377 sampled_row[s] = global_sampled_row[gs];
358-
359- /* Load MGmol pointer and Potentials */
360- MGmol<OrbitalsType> *mgmol = static_cast <MGmol<OrbitalsType> *>(mgmol_);
361- Poisson *poisson = mgmol->electrostat_ ->getPoissonSolver ();
362- Potentials& pot = mgmol->getHamiltonian ()->potential ();
363- std::shared_ptr<Rho<OrbitalsType>> rho = mgmol->getRho ();
364- const int dim = pot.size ();
365378
366379 /* ROM currently support only nspin=1 */
367380 CAROM_VERIFY (rho->rho_ .size () == 1 );
@@ -404,19 +417,70 @@ void runPoissonROM(MGmolInterface *mgmol_)
404417 /* compute ROM rho using hyper reduction */
405418 CAROM::Vector sample_rho (1 , true ); // this will be resized in computeRhoOnSamplePts
406419 computeRhoOnSamplePts (dm, psi, rom_psi, sampled_row, sample_rho);
420+
421+ /* check sampled rho */
422+ for (int s = 0 ; s < sampled_row.size (); s++)
423+ {
424+ printf (" rank %d, rho[%d]: %.5e, sample_rho: %.5e\n " ,
425+ rank, sampled_row[s], rho->rho_ [0 ][sampled_row[s]], sample_rho (s));
426+ }
427+
407428 sample_rho.gather ();
408429 CAROM::Vector *rom_rho = pot_rhs_rom.mult (sample_rho);
430+ if (rank == 0 )
431+ {
432+ printf (" rom rho before projection\n " );
433+ for (int d = 0 ; d < num_pot_basis; d++)
434+ printf (" %.5e\t " , rom_rho->item (d));
435+ printf (" \n " );
436+
437+ printf (" pot_rhs_rescaler\n " );
438+ for (int d = 0 ; d < num_pot_basis; d++)
439+ printf (" %.5e\t " , pot_rhs_rescaler.item (d));
440+ printf (" \n " );
441+ }
409442
410443 /* rescale the electron density */
411444 const double nel = ct.getNel ();
412445 // volume element is already multiplied in pot_rhs_rescaler.
413446 const double tcharge = rom_rho->inner_product (pot_rhs_rescaler);
414447 *rom_rho *= nel / tcharge;
448+ if (rank == 0 )
449+ printf (" rank %d, rho scaler: %.3e\n " , rank, nel / tcharge);
450+
451+ /* check rho projection */
452+ CAROM::Vector fom_rho_vec (&rho->rho_ [0 ][0 ], dim, true , false );
453+ CAROM::Vector *rho_proj = pot_basis->transposeMult (fom_rho_vec);
454+ CAROM::Vector *rho_proj2 = pot_basis->mult (*rho_proj);
455+ (*rho_proj2) -= fom_rho_vec;
456+ double rho_proj_error = rho_proj2->norm () / fom_rho_vec.norm ();
457+ if (rank == 0 )
458+ {
459+ printf (" rom rho\n " );
460+ for (int d = 0 ; d < num_pot_basis; d++)
461+ printf (" %.5e\t " , rom_rho->item (d));
462+ printf (" \n " );
463+ printf (" fom rho projection\n " );
464+ for (int d = 0 ; d < num_pot_basis; d++)
465+ printf (" %.5e\t " , rho_proj->item (d));
466+ printf (" \n " );
467+
468+ printf (" rho proj error: %.5e\n " , rho_proj_error);
469+ }
415470
416471 /* compute ROM ion density using hyper reduction */
417472 std::shared_ptr<Ions> ions = mgmol->getIons ();
418473 CAROM::Vector sampled_rhoc (1 , true ); // this will be resized in evalIonDensityOnSamplePts
419474 pot.evalIonDensityOnSamplePts (*ions, sampled_row, sampled_rhoc);
475+
476+ /* check sampled rhoc */
477+ RHODTYPE *rho_comp = pot.rho_comp ();
478+ for (int s = 0 ; s < sampled_row.size (); s++)
479+ {
480+ printf (" rank %d, rhoc[%d]: %.5e, sampled_rhoc: %.5e\n " ,
481+ rank, sampled_row[s], rho_comp[sampled_row[s]], sampled_rhoc (s));
482+ }
483+
420484 sampled_rhoc.gather ();
421485 CAROM::Vector *rom_rhoc = pot_rhs_rom.mult (sampled_rhoc);
422486
@@ -425,6 +489,8 @@ void runPoissonROM(MGmolInterface *mgmol_)
425489 // volume element is already multiplied in pot_rhs_rescaler.
426490 const double comp_rho = rom_rhoc->inner_product (pot_rhs_rescaler);
427491 *rom_rhoc *= ionic_charge / comp_rho;
492+ if (rank == 0 )
493+ printf (" rank %d, rhoc scaler: %.3e\n " , rank, ionic_charge / comp_rho);
428494
429495 /* right-hand side */
430496 *rom_rho -= (*rom_rhoc);
@@ -433,10 +499,48 @@ void runPoissonROM(MGmolInterface *mgmol_)
433499 /* solve Poisson ROM */
434500 CAROM::Vector *rom_pot = pot_rom_inv.mult (*rom_rho);
435501
502+ /* data array to lift up rom solution */
503+ std::vector<POTDTYPE> test_sol (dim);
504+ /* get librom view-vector of test_sol[s] */
505+ CAROM::Vector test_sol_vec (test_sol.data (), dim, true , false );
506+ pot_basis->mult (*rom_pot, test_sol_vec);
507+
508+ /* mgmol grid function for lifted-up fom solution */
509+ pb::GridFunc<POTDTYPE> testsol_gf (grid, bc[0 ], bc[1 ], bc[2 ]);
510+ pb::GridFunc<POTDTYPE> fomsol_gf (grid, bc[0 ], bc[1 ], bc[2 ]);
511+ testsol_gf.assign (test_sol.data (), ' d' );
512+ // POTDTYPE *vh_rho = pot.vh_rho();
513+ // for (int d = 0; d < dim; d++)
514+ // (vh_rho[d]) += 1.0e-3;
515+ fomsol_gf.assign (pot.vh_rho (), ' d' );
516+
517+ testsol_gf -= fomsol_gf;
518+ double rel_error = testsol_gf.norm2 () / fomsol_gf.norm2 ();
519+ if (rank == 0 )
520+ printf (" relative error: %.3e\n " , rel_error);
521+
522+ /* librom view vector for fom solution */
523+ CAROM::Vector fom_sol_vec (pot.vh_rho (), dim, true , false );
524+ CAROM::Vector *fom_proj = pot_basis->transposeMult (fom_sol_vec);
525+ if (rank == 0 )
526+ {
527+ printf (" rom vector\n " );
528+ for (int d = 0 ; d < num_pot_basis; d++)
529+ printf (" %.5e\t " , rom_pot->item (d));
530+ printf (" \n " );
531+ printf (" fom projection\n " );
532+ for (int d = 0 ; d < num_pot_basis; d++)
533+ printf (" %.5e\t " , fom_proj->item (d));
534+ printf (" \n " );
535+ }
536+
436537 /* clean up */
437538 delete rom_rho;
438539 delete rom_rhoc;
439540 delete rom_pot;
541+ delete fom_proj;
542+ delete rho_proj;
543+ delete rho_proj2;
440544}
441545
442546/* test routines */
@@ -713,6 +817,12 @@ void testROMRhoOperator(MGmolInterface *mgmol_)
713817 const OrthoType ortho_type = rho->getOrthoType ();
714818 assert (ortho_type == OrthoType::Nonorthogonal);
715819
820+ /* GridFunc initialization inputs */
821+ const pb::Grid &grid (poisson->vh ().grid ());
822+ short bc[3 ];
823+ for (int d = 0 ; d < 3 ; d++)
824+ bc[d] = poisson->vh ().bc (d);
825+
716826 /* potential should have the same size as rho */
717827 const int dim = pot.size ();
718828
@@ -734,11 +844,24 @@ void testROMRhoOperator(MGmolInterface *mgmol_)
734844
735845 /* Collect the restart files */
736846 std::string filename;
847+ pb::GridFunc<POTDTYPE> rhogf (grid, bc[0 ], bc[1 ], bc[2 ]);
848+ std::vector<RHODTYPE> rho_outvec (rho->rho_ [0 ].size ());
737849 for (int k = minidx; k <= maxidx; k++)
738850 {
739851 filename = string_format (rom_options.restart_file_fmt , k);
740852 mgmol->loadRestartFile (filename);
741853 basis_generator.takeSample (&rho->rho_ [0 ][0 ]);
854+
855+ rhogf.assign (&rho->rho_ [0 ][0 ]);
856+ rhogf.init_vect (rho_outvec.data (), ' d' );
857+ for (int d = 0 ; d < rho_outvec.size (); d++)
858+ {
859+ const double error = abs (rho->rho_ [0 ][d] - rho_outvec[d]);
860+ if (error > 0.0 )
861+ printf (" rank %d, rho[%d]: %.15e, sample_rho: %.15e\n " ,
862+ rank, d, rho->rho_ [0 ][d], rho_outvec[d]);
863+ CAROM_VERIFY (error == 0.0 );
864+ }
742865 }
743866 // basis_generator.writeSnapshot();
744867 const CAROM::Matrix rho_snapshots (*basis_generator.getSnapshotMatrix ());
0 commit comments