From f78c3b0e60b2eece352faabf7cf997e08b3a2642 Mon Sep 17 00:00:00 2001 From: Steven Hahn Date: Wed, 30 Aug 2023 11:31:25 -0400 Subject: [PATCH] Add missing implementation to SPOSetBuilderT Signed-off-by: Steven Hahn --- src/QMCWaveFunctions/SPOSetBuilderT.cpp | 288 ++++++++++++++++++++++++ 1 file changed, 288 insertions(+) diff --git a/src/QMCWaveFunctions/SPOSetBuilderT.cpp b/src/QMCWaveFunctions/SPOSetBuilderT.cpp index a75198631b..389c91684e 100644 --- a/src/QMCWaveFunctions/SPOSetBuilderT.cpp +++ b/src/QMCWaveFunctions/SPOSetBuilderT.cpp @@ -35,6 +35,294 @@ void SPOSetBuilderT::reserve_states(int nsets) states.push_back(std::make_unique()); } +template<> +std::unique_ptr> SPOSetBuilderT::createSPOSet(xmlNodePtr cur) +{ + std::string spo_object_name; + std::string optimize("no"); + + OhmmsAttributeSet attrib; + attrib.add(spo_object_name, "id"); + attrib.add(spo_object_name, "name"); + attrib.add(optimize, "optimize"); + attrib.put(cur); + + app_summary() << std::endl; + app_summary() << " Single particle orbitals (SPO)" << std::endl; + app_summary() << " ------------------------------" << std::endl; + app_summary() << " Name: " << spo_object_name << " Type: " << type_name_ + << " Builder class name: " << ClassName << std::endl; + app_summary() << std::endl; + + if (spo_object_name.empty()) + myComm->barrier_and_abort("SPOSet object \"name\" attribute not given in the input!"); + + // read specialized sposet construction requests + // and translate them into a set of orbital indices + SPOSetInputInfo input_info(cur); + + // process general sposet construction requests + // and preserve legacy interface + std::unique_ptr> sposet; + + try + { + if (legacy && input_info.legacy_request) + sposet = createSPOSetFromXML(cur); + else + sposet = createSPOSet(cur, input_info); + } + catch (const UniformCommunicateError& ue) + { + myComm->barrier_and_abort(ue.what()); + } + + if (!sposet) + myComm->barrier_and_abort("SPOSetBuilder::createSPOSet sposet creation failed"); + + if (optimize == "rotation" || optimize == "yes") + { + app_warning() << "Specifying orbital rotation via optimize tag is deprecated. Use the rotated_spo element instead" + << std::endl; + + sposet->storeParamsBeforeRotation(); + // create sposet with rotation + auto& sposet_ref = *sposet; + app_log() << " SPOSet " << sposet_ref.getName() << " is optimizable\n"; + if (!sposet_ref.isRotationSupported()) + myComm->barrier_and_abort("Orbital rotation not supported with '" + sposet_ref.getName() + "' of type '" + + sposet_ref.getClassName() + "'."); + auto rot_spo = std::make_unique>(sposet_ref.getName(), std::move(sposet)); + xmlNodePtr tcur = cur->xmlChildrenNode; + while (tcur != NULL) + { + std::string cname((const char*)(tcur->name)); + if (cname == "opt_vars") + { + std::vector params; + putContent(params, tcur); + rot_spo->setRotationParameters(params); + } + tcur = tcur->next; + } + sposet = std::move(rot_spo); + } + + if (sposet->getName().empty()) + app_warning() << "SPOSet object doesn't have a name." << std::endl; + if (!spo_object_name.empty() && sposet->getName() != spo_object_name) + app_warning() << "SPOSet object name mismatched! input name: " << spo_object_name + << " object name: " << sposet->getName() << std::endl; + + sposet->checkObject(); + return sposet; +} + +template<> +std::unique_ptr> SPOSetBuilderT::createSPOSet(xmlNodePtr cur) +{ + std::string spo_object_name; + std::string optimize("no"); + + OhmmsAttributeSet attrib; + attrib.add(spo_object_name, "id"); + attrib.add(spo_object_name, "name"); + attrib.add(optimize, "optimize"); + attrib.put(cur); + + app_summary() << std::endl; + app_summary() << " Single particle orbitals (SPO)" << std::endl; + app_summary() << " ------------------------------" << std::endl; + app_summary() << " Name: " << spo_object_name << " Type: " << type_name_ + << " Builder class name: " << ClassName << std::endl; + app_summary() << std::endl; + + if (spo_object_name.empty()) + myComm->barrier_and_abort("SPOSet object \"name\" attribute not given in the input!"); + + // read specialized sposet construction requests + // and translate them into a set of orbital indices + SPOSetInputInfo input_info(cur); + + // process general sposet construction requests + // and preserve legacy interface + std::unique_ptr> sposet; + + try + { + if (legacy && input_info.legacy_request) + sposet = createSPOSetFromXML(cur); + else + sposet = createSPOSet(cur, input_info); + } + catch (const UniformCommunicateError& ue) + { + myComm->barrier_and_abort(ue.what()); + } + + if (!sposet) + myComm->barrier_and_abort("SPOSetBuilder::createSPOSet sposet creation failed"); + + if (optimize == "rotation" || optimize == "yes") + { + app_warning() << "Specifying orbital rotation via optimize tag is deprecated. Use the rotated_spo element instead" + << std::endl; + + sposet->storeParamsBeforeRotation(); + // create sposet with rotation + auto& sposet_ref = *sposet; + app_log() << " SPOSet " << sposet_ref.getName() << " is optimizable\n"; + if (!sposet_ref.isRotationSupported()) + myComm->barrier_and_abort("Orbital rotation not supported with '" + sposet_ref.getName() + "' of type '" + + sposet_ref.getClassName() + "'."); + auto rot_spo = std::make_unique>(sposet_ref.getName(), std::move(sposet)); + xmlNodePtr tcur = cur->xmlChildrenNode; + while (tcur != NULL) + { + std::string cname((const char*)(tcur->name)); + if (cname == "opt_vars") + { + std::vector params; + putContent(params, tcur); + rot_spo->setRotationParameters(params); + } + tcur = tcur->next; + } + sposet = std::move(rot_spo); + } + + if (sposet->getName().empty()) + app_warning() << "SPOSet object doesn't have a name." << std::endl; + if (!spo_object_name.empty() && sposet->getName() != spo_object_name) + app_warning() << "SPOSet object name mismatched! input name: " << spo_object_name + << " object name: " << sposet->getName() << std::endl; + + sposet->checkObject(); + return sposet; +} + +template<> +std::unique_ptr>> SPOSetBuilderT>::createSPOSet(xmlNodePtr cur) +{ + std::string spo_object_name; + std::string optimize("no"); + + OhmmsAttributeSet attrib; + attrib.add(spo_object_name, "id"); + attrib.add(spo_object_name, "name"); + attrib.add(optimize, "optimize"); + attrib.put(cur); + + app_summary() << std::endl; + app_summary() << " Single particle orbitals (SPO)" << std::endl; + app_summary() << " ------------------------------" << std::endl; + app_summary() << " Name: " << spo_object_name << " Type: " << type_name_ + << " Builder class name: " << ClassName << std::endl; + app_summary() << std::endl; + + if (spo_object_name.empty()) + myComm->barrier_and_abort("SPOSet object \"name\" attribute not given in the input!"); + + // read specialized sposet construction requests + // and translate them into a set of orbital indices + SPOSetInputInfo input_info(cur); + + // process general sposet construction requests + // and preserve legacy interface + std::unique_ptr>> sposet; + + try + { + if (legacy && input_info.legacy_request) + sposet = createSPOSetFromXML(cur); + else + sposet = createSPOSet(cur, input_info); + } + catch (const UniformCommunicateError& ue) + { + myComm->barrier_and_abort(ue.what()); + } + + if (!sposet) + myComm->barrier_and_abort("SPOSetBuilder::createSPOSet sposet creation failed"); + + if (optimize == "rotation" || optimize == "yes") + { + app_error() << "Orbital optimization via rotation doesn't support complex wavefunction yet.\n"; + abort(); + } + + if (sposet->getName().empty()) + app_warning() << "SPOSet object doesn't have a name." << std::endl; + if (!spo_object_name.empty() && sposet->getName() != spo_object_name) + app_warning() << "SPOSet object name mismatched! input name: " << spo_object_name + << " object name: " << sposet->getName() << std::endl; + + sposet->checkObject(); + return sposet; +} + +template<> +std::unique_ptr>> SPOSetBuilderT>::createSPOSet(xmlNodePtr cur) +{ + std::string spo_object_name; + std::string optimize("no"); + + OhmmsAttributeSet attrib; + attrib.add(spo_object_name, "id"); + attrib.add(spo_object_name, "name"); + attrib.add(optimize, "optimize"); + attrib.put(cur); + + app_summary() << std::endl; + app_summary() << " Single particle orbitals (SPO)" << std::endl; + app_summary() << " ------------------------------" << std::endl; + app_summary() << " Name: " << spo_object_name << " Type: " << type_name_ + << " Builder class name: " << ClassName << std::endl; + app_summary() << std::endl; + + if (spo_object_name.empty()) + myComm->barrier_and_abort("SPOSet object \"name\" attribute not given in the input!"); + + // read specialized sposet construction requests + // and translate them into a set of orbital indices + SPOSetInputInfo input_info(cur); + + // process general sposet construction requests + // and preserve legacy interface + std::unique_ptr>> sposet; + + try + { + if (legacy && input_info.legacy_request) + sposet = createSPOSetFromXML(cur); + else + sposet = createSPOSet(cur, input_info); + } + catch (const UniformCommunicateError& ue) + { + myComm->barrier_and_abort(ue.what()); + } + + if (!sposet) + myComm->barrier_and_abort("SPOSetBuilder::createSPOSet sposet creation failed"); + + if (optimize == "rotation" || optimize == "yes") + { + app_error() << "Orbital optimization via rotation doesn't support complex wavefunction yet.\n"; + abort(); + } + + if (sposet->getName().empty()) + app_warning() << "SPOSet object doesn't have a name." << std::endl; + if (!spo_object_name.empty() && sposet->getName() != spo_object_name) + app_warning() << "SPOSet object name mismatched! input name: " << spo_object_name + << " object name: " << sposet->getName() << std::endl; + + sposet->checkObject(); + return sposet; +} + template std::unique_ptr> SPOSetBuilderT::createSPOSet(xmlNodePtr cur, SPOSetInputInfo& input_info) {