55#include " ace-evaluator/ace_types.h"
66#include " ace/ace_yaml_input.h"
77#include " ace-evaluator/ace_radial.h"
8+ #include " cnpy/cnpy.h"
89
910#define sqr (x ) ((x)*(x))
1011const DOUBLE_TYPE pi = 3.14159265358979323846264338327950288419 ; // pi
@@ -406,8 +407,6 @@ void TDACEBEvaluator::compute_atom(int i, DOUBLE_TYPE **x, const SPECIES_TYPE *t
406407
407408 const SHORT_INT_TYPE total_basis_size = basis_set.basis [mu_i].size ();
408409
409- // const auto& basis = basis_set.basis[mu_i];
410-
411410 const DENSITY_TYPE ndensity = basis_set.embedding_specifications .ndensity ;
412411
413412 neighbours_forces.resize (jnum, 3 );
@@ -417,6 +416,14 @@ void TDACEBEvaluator::compute_atom(int i, DOUBLE_TYPE **x, const SPECIES_TYPE *t
417416 A.fill (0 );
418417 rhos.fill (0 );
419418 dF_drho.fill (0 );
419+
420+ #ifdef EXTRA_C_PROJECTIONS
421+ if (this ->compute_projections ) {
422+ projections.init (total_basis_size, " projections" );
423+ projections.fill (0 );
424+ }
425+ #endif
426+
420427 setup_timer.stop ();
421428
422429 A_construction_timer.start ();
@@ -557,6 +564,12 @@ void TDACEBEvaluator::compute_atom(int i, DOUBLE_TYPE **x, const SPECIES_TYPE *t
557564 dB_flatten (func_ms_t_ind) = dB;
558565 }
559566
567+ #ifdef EXTRA_C_PROJECTIONS
568+ if (this ->compute_projections ) {
569+ // aggregate C-projections separately
570+ projections (func_ind) += B * gen_cgs_flatten (gen_cgs_shift + ms_ind);
571+ }
572+ #endif
560573
561574 for (DENSITY_TYPE p = 0 ; p < ndensity; ++p) {
562575 // real-part only multiplication
@@ -647,6 +660,30 @@ void TDACEBEvaluator::compute_atom(int i, DOUBLE_TYPE **x, const SPECIES_TYPE *t
647660
648661 e_atom = basis_set.scale * evdwl + basis_set.shift + basis_set.E0_shift .at (mu_i);
649662
663+ #ifdef EXTRA_C_PROJECTIONS
664+ if (this ->compute_projections ) {
665+ // check if active set is loaded
666+ // use dE_dc or projections as asi_vector
667+ if (A_active_set_inv.find (mu_i) != A_active_set_inv.end ()) {
668+ Array1D<DOUBLE_TYPE> &asi_vector = this ->projections ;
669+ // get inverted active set for current species type
670+ const auto &A_as_inv = A_active_set_inv.at (mu_i);
671+
672+ DOUBLE_TYPE gamma_max = 0 ;
673+ for (int i = 0 ; i < A_as_inv.get_dim (0 ); i++) {
674+ DOUBLE_TYPE current_gamma = 0 ;
675+ // compute row-matrix-multiplication asi_vector * A_as_inv (transposed matrix)
676+ for (int k = 0 ; k < asi_vector.get_dim (0 ); k++)
677+ current_gamma += asi_vector (k) * A_as_inv (i, k);
678+
679+ if (abs (current_gamma) > gamma_max)
680+ gamma_max = abs (current_gamma);
681+ }
682+
683+ max_gamma_grade = gamma_max;
684+ }
685+ }
686+ #endif
650687 per_atom_calc_timer.stop ();
651688}
652689
@@ -660,6 +697,55 @@ void TDACEBEvaluator::init_timers() {
660697 setup_timer.init ();
661698}
662699
700+
701+ void TDACEBEvaluator::load_active_set (const string &asi_filename) {
702+ cnpy::npz_t asi_npz = cnpy::npz_load (asi_filename);
703+ if (asi_npz.size () != this ->basis_set .nelements ) {
704+ stringstream ss;
705+ ss << " Number of species types in ASI `" << asi_filename << " ` (" << asi_npz.size () << " )" ;
706+ ss << " not equal to number of species in TDACEBBassiSet (" << this ->basis_set .nelements << " )" ;
707+ throw std::runtime_error (ss.str ());
708+ }
709+
710+ for (auto &kv: asi_npz) {
711+ auto element_name = kv.first ;
712+ SPECIES_TYPE st = this ->basis_set .elements_to_index_map .at (element_name);
713+ auto shape = kv.second .shape ;
714+ // auto_determine extrapolation grade type: linear or non-linear
715+ // validate_ASI_square_shape(st, shape);
716+ if (shape.at (0 ) != shape.at (1 )) {
717+ stringstream ss;
718+ ss << " Active Set Inverted for element `" << element_name << " `:" ;
719+ ss << " should be square matrix, but has shape (" << shape.at (0 ) << " , " << shape.at (1 ) << " )" ;
720+ throw runtime_error (ss.str ());
721+ }
722+ // validate_ASI_shape(element_name, st, shape);
723+ int expected_ASI_size = this ->basis_set .basis [st].size ();
724+ if (expected_ASI_size != shape.at (0 )) {
725+ stringstream ss;
726+ ss << " Active Set Inverted for element `" << element_name << " `:" ;
727+ ss << " expected shape: (" << expected_ASI_size << " , " << expected_ASI_size << " ) , but has shape ("
728+ << shape.at (0 ) << " , " << shape.at (1 ) << " )" ;
729+ throw runtime_error (ss.str ());
730+ }
731+
732+ Array2D<DOUBLE_TYPE> A0_inv (shape.at (0 ), shape.at (1 ), element_name);
733+ auto data_vec = kv.second .as_vec <DOUBLE_TYPE>();
734+ A0_inv.set_flatten_vector (data_vec);
735+ // transpose matrix to speed-up vec-mat multiplication
736+ Array2D<DOUBLE_TYPE> A0_inv_transpose (A0_inv.get_dim (1 ), A0_inv.get_dim (0 ));
737+
738+ for (int i = 0 ; i < A0_inv.get_dim (0 ); i++)
739+ for (int j = 0 ; j < A0_inv.get_dim (1 ); j++)
740+ A0_inv_transpose (j, i) = A0_inv (i, j);
741+
742+ this ->A_active_set_inv [st] = A0_inv_transpose;
743+ }
744+
745+ // resize_projections();// no need, all projections are the same length
746+ }
747+
748+
663749void TDACERadialFunction::init () {
664750
665751 gr.init (nradbasemax, " gr" );
0 commit comments