LCOV - code coverage report
Current view: top level - crystdistrib - QuaternionBondProductMatrix.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 173 198 87.4 %
Date: 2025-11-25 13:55:50 Functions: 6 8 75.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-2023 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    plumed is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #include "core/ActionWithMatrix.h"
      23             : #include "core/ActionRegister.h"
      24             : #include "tools/Torsion.h"
      25             : 
      26             : 
      27             : #include <iostream>
      28             : 
      29             : namespace PLMD {
      30             : namespace crystdistrib {
      31             : 
      32             : //+PLUMEDOC MCOLVAR QUATERNION_BOND_PRODUCT_MATRIX
      33             : /*
      34             : Calculate the product between a matrix of quaternions and the bonds
      35             : 
      36             : \par Examples
      37             : 
      38             : */
      39             : //+ENDPLUMEDOC
      40             : 
      41             : class QuaternionBondProductMatrix : public ActionWithMatrix {
      42             : private:
      43             :   unsigned nderivatives;
      44             :   std::vector<bool> stored;
      45             : //  const Vector4d& rightMultiply(Tensor4d&, Vector4d&);
      46             : public:
      47             :   static void registerKeywords( Keywords& keys );
      48             :   explicit QuaternionBondProductMatrix(const ActionOptions&);
      49             :   unsigned getNumberOfDerivatives();
      50             :   unsigned getNumberOfColumns() const override ;
      51             :   void setupForTask( const unsigned& task_index, std::vector<unsigned>& indices, MultiValue& myvals ) const ;
      52             :   void performTask( const std::string& controller, const unsigned& index1, const unsigned& index2, MultiValue& myvals ) const override;
      53             :   void runEndOfRowJobs( const unsigned& ival, const std::vector<unsigned> & indices, MultiValue& myvals ) const override ;
      54             : };
      55             : 
      56             : PLUMED_REGISTER_ACTION(QuaternionBondProductMatrix,"QUATERNION_BOND_PRODUCT_MATRIX")
      57             : 
      58             : 
      59             : //const Vector4d& QuaternionBondMatrix::rightMultiply(Tensor4d& pref, Vector4d& quat) {
      60             : //  Vector4d temp;
      61             : //  int sumTemp;
      62             : //  for (int i=0; i<4; i++){ //rows
      63             : //    sumTemp=0;
      64             : //    for (int j=0; j<4; j++){ //cols
      65             : //      sumTemp+=pref(i,j)*quat[j];
      66             : //    }
      67             : //    temp[i]=sumTemp;
      68             : //  }
      69             : //  return temp;
      70             : //}
      71             : 
      72             : 
      73             : 
      74             : 
      75           7 : void QuaternionBondProductMatrix::registerKeywords( Keywords& keys ) {
      76           7 :   ActionWithMatrix::registerKeywords(keys);
      77           7 :   keys.use("ARG");
      78          14 :   keys.addOutputComponent("w","default","the real component of quaternion");
      79          14 :   keys.addOutputComponent("i","default","the i component of the quaternion");
      80          14 :   keys.addOutputComponent("j","default","the j component of the quaternion");
      81          14 :   keys.addOutputComponent("k","default","the k component of the quaternion");
      82           7 : }
      83             : 
      84           4 : QuaternionBondProductMatrix::QuaternionBondProductMatrix(const ActionOptions&ao):
      85             :   Action(ao),
      86           4 :   ActionWithMatrix(ao) {
      87           4 :   if( getNumberOfArguments()!=8 ) {
      88           0 :     error("should be eight arguments to this action, 4 quaternion components and 4 matrices");
      89             :   }
      90           4 :   unsigned nquat = getPntrToArgument(0)->getNumberOfValues();
      91          20 :   for(unsigned i=0; i<4; ++i) {
      92             :     Value* myarg=getPntrToArgument(i);
      93          16 :     myarg->buildDataStore();
      94          16 :     if( myarg->getRank()!=1 ) {
      95           0 :       error("first four arguments to this action should be vectors");
      96             :     }
      97          16 :     if( (myarg->getPntrToAction())->getName()!="QUATERNION_VECTOR" ) {
      98           0 :       error("first four arguments to this action should be quaternions");
      99             :     }
     100          16 :     std::string mylab=getPntrToArgument(i)->getName();
     101          16 :     std::size_t dot=mylab.find_first_of(".");
     102          24 :     if( i==0 && mylab.substr(dot+1)!="w" ) {
     103           0 :       error("quaternion arguments are in wrong order");
     104             :     }
     105          24 :     if( i==1 && mylab.substr(dot+1)!="i" ) {
     106           0 :       error("quaternion arguments are in wrong order");
     107             :     }
     108          24 :     if( i==2 && mylab.substr(dot+1)!="j" ) {
     109           0 :       error("quaternion arguments are in wrong order");
     110             :     }
     111          24 :     if( i==3 && mylab.substr(dot+1)!="k" ) {
     112           0 :       error("quaternion arguments are in wrong order");
     113             :     }
     114             :   }
     115           4 :   std::vector<unsigned> shape( getPntrToArgument(4)->getShape() );
     116          20 :   for(unsigned i=4; i<8; ++i) {
     117             :     Value* myarg=getPntrToArgument(i);
     118          16 :     if( myarg->getRank()!=2 ) {
     119           0 :       error("second four arguments to this action should be matrices");
     120             :     }
     121          16 :     if( myarg->getShape()[0]!=shape[0] || myarg->getShape()[1]!=shape[1] ) {
     122           0 :       error("matrices should all have the same shape");
     123             :     }
     124          16 :     if( myarg->getShape()[0]!=nquat ) {
     125           0 :       error("number of rows in matrix should equal number of input quaternions");
     126             :     }
     127          16 :     std::string mylab=getPntrToArgument(i)->getName();
     128          16 :     std::size_t dot=mylab.find_first_of(".");
     129          24 :     if( i==5 && mylab.substr(dot+1)!="x" ) {
     130           0 :       error("quaternion arguments are in wrong order");
     131             :     }
     132          24 :     if( i==6 && mylab.substr(dot+1)!="y" ) {
     133           0 :       error("quaternion arguments are in wrong order");
     134             :     }
     135          24 :     if( i==7 && mylab.substr(dot+1)!="z" ) {
     136           0 :       error("quaternion arguments are in wrong order");
     137             :     }
     138             :   }
     139           4 :   addComponent( "w", shape );
     140           4 :   componentIsNotPeriodic("w");
     141           4 :   addComponent( "i", shape );
     142           4 :   componentIsNotPeriodic("i");
     143           4 :   addComponent( "j", shape );
     144           4 :   componentIsNotPeriodic("j");
     145           4 :   addComponent( "k", shape );
     146           4 :   componentIsNotPeriodic("k");
     147           4 :   done_in_chain=true;
     148           4 :   nderivatives = buildArgumentStore(0);
     149             : 
     150           4 :   std::string headstr=getFirstActionInChain()->getLabel();
     151           4 :   stored.resize( getNumberOfArguments() );
     152          36 :   for(unsigned i=0; i<getNumberOfArguments(); ++i) {
     153          32 :     stored[i] = getPntrToArgument(i)->ignoreStoredValue( headstr );
     154             :   }
     155           4 : }
     156             : 
     157          32 : unsigned QuaternionBondProductMatrix::getNumberOfDerivatives() {
     158          32 :   return nderivatives;
     159             : }
     160             : 
     161          96 : unsigned QuaternionBondProductMatrix::getNumberOfColumns() const {
     162          96 :   const ActionWithMatrix* am=dynamic_cast<const ActionWithMatrix*>( getPntrToArgument(4)->getPntrToAction() );
     163          96 :   plumed_assert( am );
     164          96 :   return am->getNumberOfColumns();
     165             : }
     166             : 
     167           0 : void QuaternionBondProductMatrix::setupForTask( const unsigned& task_index, std::vector<unsigned>& indices, MultiValue& myvals ) const {
     168           0 :   unsigned start_n = getPntrToArgument(4)->getShape()[0], size_v = getPntrToArgument(4)->getShape()[1];
     169           0 :   if( indices.size()!=size_v+1 ) {
     170           0 :     indices.resize( size_v+1 );
     171             :   }
     172           0 :   for(unsigned i=0; i<size_v; ++i) {
     173           0 :     indices[i+1] = start_n + i;
     174             :   }
     175             :   myvals.setSplitIndex( size_v + 1 );
     176           0 : }
     177             : 
     178      381366 : void QuaternionBondProductMatrix::performTask( const std::string& controller, const unsigned& index1, const unsigned& index2, MultiValue& myvals ) const {
     179      381366 :   unsigned ind2=index2;
     180      381366 :   if( index2>=getPntrToArgument(0)->getShape()[0] ) {
     181           0 :     ind2 = index2 - getPntrToArgument(0)->getShape()[0];
     182             :   }
     183             : 
     184      381366 :   std::vector<double> quat(4), bond(4), quatTemp(4);
     185      381366 :   std::vector<Tensor4d> dqt(2); //dqt[0] -> derivs w.r.t quat [dwt/dw1 dwt/di1 dwt/dj1 dwt/dk1]
     186             :   //[dit/dw1 dit/di1 dit/dj1 dit/dk1] etc, and dqt[1] is w.r.t the vector-turned-quaternion called bond
     187             : 
     188             :   // Retrieve the quaternion
     189     1906830 :   for(unsigned i=0; i<4; ++i) {
     190     1525464 :     quat[i] = getArgumentElement( i, index1, myvals );
     191             :   }
     192             : 
     193             :   // Retrieve the components of the matrix
     194      381366 :   double weight = getElementOfMatrixArgument( 4, index1, ind2, myvals );
     195     1525464 :   for(unsigned i=1; i<4; ++i) {
     196     1144098 :     bond[i] = getElementOfMatrixArgument( 4+i, index1, ind2, myvals );
     197             :   }
     198             : 
     199             :   // calculate normalization factor
     200      381366 :   bond[0]=0.0;
     201      381366 :   double normFac = 1/sqrt(bond[1]*bond[1] + bond[2]*bond[2] + bond[3]*bond[3]);
     202      381366 :   if (bond[1] == 0.0 && bond[2]==0.0 && bond[3]==0) {
     203             :     normFac=1;  //just for the case where im comparing a quat to itself, itll be 0 at the end anyway
     204             :   }
     205             :   double normFac3 = normFac*normFac*normFac;
     206             :   //I hold off on normalizing because this can be done at the very end, and it makes the derivatives with respect to 'bond' more simple
     207             : 
     208             : 
     209             : 
     210      381366 :   std::vector<double> quat_conj(4);
     211      381366 :   quat_conj[0] = quat[0];
     212      381366 :   quat_conj[1] = -1*quat[1];
     213      381366 :   quat_conj[2] = -1*quat[2];
     214      381366 :   quat_conj[3] = -1*quat[3];
     215             :   //make a conjugate of q1 my own sanity
     216             : 
     217             : 
     218             : 
     219             : 
     220             : //q1_conj * r first, while keep track of derivs
     221             :   double pref=1;
     222             :   double conj=1;
     223             :   double pref2=1;
     224             :   //real part of q1*q2
     225             : 
     226     1906830 :   for(unsigned i=0; i<4; ++i) {
     227     1525464 :     if( i>0 ) {
     228             :       pref=-1;
     229             :       conj=-1;
     230             :       pref2=-1;
     231             :     }
     232     1525464 :     quatTemp[0]+=pref*quat_conj[i]*bond[i];
     233     1525464 :     dqt[0](0,i) = conj*pref*bond[i];
     234     1525464 :     dqt[1](0,i) = pref2*quat_conj[i];
     235             :     //addDerivativeOnVectorArgument( false, 0, i, index1, conj*pref*bond[i], myvals );
     236             :     //addDerivativeOnVectorArgument( false, 0, 4+i, ind2, conj*pref*quat[i], myvals );
     237             :   }
     238             :   //i component
     239             :   pref=1;
     240             :   conj=1;
     241             :   pref2=1;
     242             : 
     243     1906830 :   for (unsigned i=0; i<4; i++) {
     244     1525464 :     if(i==3) {
     245             :       pref=-1;
     246             :     } else {
     247             :       pref=1;
     248             :     }
     249     1525464 :     if(i==2) {
     250             :       pref2=-1;
     251             :     } else {
     252             :       pref2=1;
     253             :     }
     254     1525464 :     if (i>0) {
     255             :       conj=-1;
     256             :     }
     257             : 
     258     1525464 :     quatTemp[1]+=pref*quat_conj[i]*bond[(5-i)%4];
     259     1525464 :     dqt[0](1,i) =conj*pref*bond[(5-i)%4];
     260     1525464 :     dqt[1](1,i) = pref2*quat_conj[(5-i)%4];
     261             :     //addDerivativeOnVectorArgument( false, 1, i, index1, conj*pref*bond[(5-i)%4], myvals );
     262             :     //addDerivativeOnVectorArgument( false, 1, 4+i, ind2, conj*pref*quat[i], myvals );
     263             :   }
     264             : 
     265             :   //j component
     266             :   pref=1;
     267             :   pref2=1;
     268             :   conj=1;
     269             : 
     270     1906830 :   for (unsigned i=0; i<4; i++) {
     271     1525464 :     if(i==1) {
     272             :       pref=-1;
     273             :     } else {
     274             :       pref=1;
     275             :     }
     276     1525464 :     if (i==3) {
     277             :       pref2=-1;
     278             :     } else {
     279             :       pref2=1;
     280             :     }
     281     1525464 :     if (i>0) {
     282             :       conj=-1;
     283             :     }
     284             : 
     285     1525464 :     quatTemp[2]+=pref*quat_conj[i]*bond[(i+2)%4];
     286     1525464 :     dqt[0](2,i)=conj*pref*bond[(i+2)%4];
     287     1525464 :     dqt[1](2,i)=pref2*quat_conj[(i+2)%4];
     288             :     //addDerivativeOnVectorArgument( false, 2, i, index1, conj*pref*bond[(i+2)%4], myvals );
     289             :     //addDerivativeOnVectorArgument( false, 2, 4+i, ind2, conj*pref*quat[i], myvals );
     290             :   }
     291             : 
     292             :   //k component
     293             :   pref=1;
     294             :   pref2=1;
     295             :   conj=1;
     296             : 
     297     1906830 :   for (unsigned i=0; i<4; i++) {
     298     1525464 :     if(i==2) {
     299             :       pref=-1;
     300             :     } else {
     301             :       pref=1;
     302             :     }
     303     1525464 :     if(i==1) {
     304             :       pref2=-1;
     305             :     } else {
     306             :       pref2=1;
     307             :     }
     308     1525464 :     if(i>0) {
     309             :       conj=-1;
     310             :     }
     311     1525464 :     quatTemp[3]+=pref*quat_conj[i]*bond[(3-i)];
     312     1525464 :     dqt[0](3,i)=conj*pref*bond[3-i];
     313     1525464 :     dqt[1](3,i)= pref2*quat_conj[3-i];
     314             :     //addDerivativeOnVectorArgument( false, 3, i, index1, conj*pref*bond[3-i], myvals );
     315             :     //addDerivativeOnVectorArgument( false, 3, 4+i, ind2, conj*pref*quat[i], myvals );
     316             : 
     317             :   }
     318             : 
     319             : 
     320             : //now previous ^ product times quat again, not conjugated
     321             :   //real part of q1*q2
     322      381366 :   double tempDot=0,wf=0,xf=0,yf=0,zf=0;
     323             :   pref=1;
     324             :   pref2=1;
     325     1906830 :   for(unsigned i=0; i<4; ++i) {
     326     1525464 :     if( i>0 ) {
     327             :       pref=-1;
     328             :       pref2=-1;
     329             :     }
     330     1525464 :     myvals.addValue( getConstPntrToComponent(0)->getPositionInStream(), normFac*pref*quatTemp[i]*quat[i] );
     331             :     wf+=normFac*pref*quatTemp[i]*quat[i];
     332     1525464 :     if( doNotCalculateDerivatives() ) {
     333           0 :       continue ;
     334             :     }
     335     1525464 :     tempDot=(dotProduct(Vector4d(quat[0],-quat[1],-quat[2],-quat[3]), dqt[0].getCol(i)) + pref2*quatTemp[i])*normFac;
     336     1525464 :     addDerivativeOnVectorArgument( stored[i], 0, i,   index1, tempDot, myvals);
     337             :   }
     338             :   //had to split because bond's derivatives depend on the value of the overall quaternion component
     339             :   //addDerivativeOnMatrixArgument( false, 0, 4, index1, ind2, 0.0, myvals );
     340     1906830 :   for(unsigned i=0; i<4; ++i) {
     341     1525464 :     tempDot=dotProduct(Vector4d(quat[0],-quat[1],-quat[2],-quat[3]), dqt[1].getCol(i))*normFac;
     342     1525464 :     if (i!=0 ) {
     343     1144098 :       addDerivativeOnMatrixArgument( stored[4+i], 0, 4+i, index1, ind2, tempDot, myvals );
     344             :     } else {
     345      381366 :       addDerivativeOnMatrixArgument( stored[4+i], 0, 4+i, index1, ind2, 0.0, myvals );
     346             :     }
     347             :   }
     348             : // for (unsigned i=0; i<4; ++i) {
     349             : //myvals.addValue( getConstPntrToComponent(0)->getPositionInStream(), 0.0 );
     350             : //if( doNotCalculateDerivatives() ) continue ;
     351             : //addDerivativeOnVectorArgument( false, 0, i,   index1, 0.0, myvals);
     352             : //addDerivativeOnVectorArgument( false, 0, 4+i, ind2, 0.0 ,  myvals);
     353             : //  }
     354             : //the w component should always be zero, barring some catastrophe, but we calculate it out anyway
     355             : 
     356             :   //i component
     357             :   pref=1;
     358             :   pref2=1;
     359     1906830 :   for (unsigned i=0; i<4; i++) {
     360     1525464 :     if(i==3) {
     361             :       pref=-1;
     362             :     } else {
     363             :       pref=1;
     364             :     }
     365     1525464 :     myvals.addValue( getConstPntrToComponent(1)->getPositionInStream(), normFac*pref*quatTemp[i]*quat[(5-i)%4]);
     366     1525464 :     xf+=normFac*pref*quatTemp[i]*quat[(5-i)%4];
     367     1525464 :     if(i==2) {
     368             :       pref2=-1;
     369             :     } else {
     370             :       pref2=1;
     371             :     }
     372     1525464 :     if( doNotCalculateDerivatives() ) {
     373           0 :       continue ;
     374             :     }
     375     1525464 :     tempDot=(dotProduct(Vector4d(quat[1],quat[0],quat[3],-quat[2]), dqt[0].getCol(i)) + pref2*quatTemp[(5-i)%4])*normFac;
     376     1525464 :     addDerivativeOnVectorArgument( stored[i], 1, i,   index1, tempDot, myvals);
     377             :   }
     378             :   //addDerivativeOnMatrixArgument( false, 1, 4, index1, ind2, 0.0, myvals );
     379             : 
     380     1906830 :   for(unsigned i=0; i<4; ++i) {
     381     1525464 :     tempDot=dotProduct(Vector4d(quat[1],quat[0],quat[3],-quat[2]), dqt[1].getCol(i))*normFac;
     382     1525464 :     if (i!=0) {
     383     1144098 :       addDerivativeOnMatrixArgument( stored[4+i], 1, 4+i, index1, ind2, tempDot+(-bond[i]*normFac*normFac*xf), myvals );
     384             :     } else {
     385      381366 :       addDerivativeOnMatrixArgument( stored[4+i], 1, 4+i, index1, ind2, 0.0, myvals );
     386             :     }
     387             : 
     388             :   }
     389             : 
     390             : 
     391             :   //j component
     392             :   pref=1;
     393             :   pref2=1;
     394     1906830 :   for (unsigned i=0; i<4; i++) {
     395     1525464 :     if(i==1) {
     396             :       pref=-1;
     397             :     } else {
     398             :       pref=1;
     399             :     }
     400     1525464 :     if (i==3) {
     401             :       pref2=-1;
     402             :     } else {
     403             :       pref2=1;
     404             :     }
     405             : 
     406     1525464 :     myvals.addValue( getConstPntrToComponent(2)->getPositionInStream(), normFac*pref*quatTemp[i]*quat[(i+2)%4]);
     407     1525464 :     yf+=normFac*pref*quatTemp[i]*quat[(i+2)%4];
     408     1525464 :     if( doNotCalculateDerivatives() ) {
     409           0 :       continue ;
     410             :     }
     411     1525464 :     tempDot=(dotProduct(Vector4d(quat[2],-quat[3],quat[0],quat[1]), dqt[0].getCol(i)) + pref2*quatTemp[(i+2)%4])*normFac;
     412     1525464 :     addDerivativeOnVectorArgument( stored[i], 2, i,   index1, tempDot, myvals);
     413             :   }
     414             :   //    addDerivativeOnMatrixArgument( false, 2, 4, index1, ind2,0.0   , myvals );
     415             : 
     416     1906830 :   for(unsigned i=0; i<4; ++i) {
     417     1525464 :     tempDot=dotProduct(Vector4d(quat[2],-quat[3],quat[0],quat[1]), dqt[1].getCol(i))*normFac;
     418     1525464 :     if (i!=0) {
     419     1144098 :       addDerivativeOnMatrixArgument( stored[4+i], 2, 4+i, index1, ind2, tempDot+(-bond[i]*normFac*normFac*yf), myvals );
     420             :     } else {
     421      381366 :       addDerivativeOnMatrixArgument( stored[4+i], 2, 4+i, index1, ind2, 0.0, myvals );
     422             :     }
     423             : 
     424             : 
     425             :   }
     426             : 
     427             :   //k component
     428             :   pref=1;
     429             :   pref2=1;
     430     1906830 :   for (unsigned i=0; i<4; i++) {
     431     1525464 :     if(i==2) {
     432             :       pref=-1;
     433             :     } else {
     434             :       pref=1;
     435             :     }
     436     1525464 :     if(i==1) {
     437             :       pref2=-1;
     438             :     } else {
     439             :       pref2=1;
     440             :     }
     441             : 
     442     1525464 :     myvals.addValue( getConstPntrToComponent(3)->getPositionInStream(), normFac*pref*quatTemp[i]*quat[(3-i)]);
     443     1525464 :     zf+=normFac*pref*quatTemp[i]*quat[(3-i)];
     444     1525464 :     if( doNotCalculateDerivatives() ) {
     445           0 :       continue ;
     446             :     }
     447     1525464 :     tempDot=(dotProduct(Vector4d(quat[3],quat[2],-quat[1],quat[0]), dqt[0].getCol(i)) + pref2*quatTemp[(3-i)])*normFac;
     448     1525464 :     addDerivativeOnVectorArgument( stored[i], 3, i,   index1, tempDot, myvals);
     449             :   }
     450             :   //addDerivativeOnMatrixArgument( false, 3, 4, index1, ind2,  0.0 , myvals );
     451             : 
     452     1906830 :   for(unsigned i=0; i<4; ++i) {
     453     1525464 :     tempDot=dotProduct(Vector4d(quat[3],quat[2],-quat[1],quat[0]), dqt[1].getCol(i))*normFac;
     454     1525464 :     if (i!=0) {
     455     1144098 :       addDerivativeOnMatrixArgument( stored[4+i], 3, 4+i, index1, ind2, tempDot+(-bond[i]*normFac*normFac*zf), myvals );
     456             :     } else {
     457      381366 :       addDerivativeOnMatrixArgument( stored[4+i], 3, 4+i, index1, ind2, 0.0, myvals );
     458             :     }
     459             : 
     460             : 
     461             :   }
     462      381366 :   if( doNotCalculateDerivatives() ) {
     463             :     return ;
     464             :   }
     465             : 
     466     1906830 :   for(unsigned outcomp=0; outcomp<4; ++outcomp) {
     467     1525464 :     unsigned ostrn = getConstPntrToComponent(outcomp)->getPositionInStream();
     468     7627320 :     for(unsigned i=4; i<8; ++i) {
     469             :       bool found=false;
     470     6101856 :       for(unsigned j=4; j<i; ++j) {
     471     4576392 :         if( arg_deriv_starts[i]==arg_deriv_starts[j] ) {
     472             :           found=true;
     473             :           break;
     474             :         }
     475             :       }
     476     6101856 :       if( found || !stored[i] ) {
     477     4576392 :         continue;
     478             :       }
     479             : 
     480             :       unsigned istrn = getPntrToArgument(i)->getPositionInStream();
     481    24407424 :       for(unsigned k=0; k<myvals.getNumberActive(istrn); ++k) {
     482    22881960 :         unsigned kind=myvals.getActiveIndex(istrn,k);
     483    22881960 :         myvals.updateIndex( ostrn, kind );
     484             :       }
     485             :     }
     486             :   }
     487             : }
     488             : 
     489        1614 : void QuaternionBondProductMatrix::runEndOfRowJobs( const unsigned& ival, const std::vector<unsigned> & indices, MultiValue& myvals ) const {
     490        1614 :   if( doNotCalculateDerivatives() || !matrixChainContinues() ) {
     491             :     return ;
     492             :   }
     493             : 
     494        8070 :   for(unsigned j=0; j<getNumberOfComponents(); ++j) {
     495        6456 :     unsigned nmat = getConstPntrToComponent(j)->getPositionInMatrixStash(), nmat_ind = myvals.getNumberOfMatrixRowDerivatives( nmat );
     496             :     std::vector<unsigned>& matrix_indices( myvals.getMatrixRowDerivativeIndices( nmat ) );
     497             :     unsigned ntwo_atoms = myvals.getSplitIndex();
     498             :     // Quaternion
     499       32280 :     for(unsigned k=0; k<4; ++k) {
     500       25824 :       matrix_indices[nmat_ind] = arg_deriv_starts[k] + ival;
     501       25824 :       nmat_ind++;
     502             :     }
     503             :     // Loop over row of matrix
     504       32280 :     for(unsigned n=4; n<8; ++n) {
     505             :       bool found=false;
     506       25824 :       for(unsigned k=4; k<n; ++k) {
     507       19368 :         if( arg_deriv_starts[k]==arg_deriv_starts[n] ) {
     508             :           found=true;
     509             :           break;
     510             :         }
     511             :       }
     512       25824 :       if( found ) {
     513             :         continue;
     514             :       }
     515             :       unsigned istrn = getPntrToArgument(n)->getPositionInMatrixStash();
     516             :       std::vector<unsigned>& imat_indices( myvals.getMatrixRowDerivativeIndices( istrn ) );
     517     4660320 :       for(unsigned k=0; k<myvals.getNumberOfMatrixRowDerivatives( istrn ); ++k) {
     518     4653864 :         matrix_indices[nmat_ind + k] = arg_deriv_starts[n] + imat_indices[k];
     519             :       }
     520        6456 :       nmat_ind += myvals.getNumberOfMatrixRowDerivatives( getPntrToArgument(4)->getPositionInMatrixStash() );
     521             :     }
     522             :     myvals.setNumberOfMatrixRowDerivatives( nmat, nmat_ind );
     523             :   }
     524             : }
     525             : 
     526             : }
     527             : }

Generated by: LCOV version 1.16