LCOV - code coverage report
Current view: top level - crystdistrib - QuaternionBondProductMatrix.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 148 153 96.7 %
Date: 2024-10-18 14:00:25 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); keys.use("ARG");
      77          14 :   keys.addOutputComponent("w","default","the real component of quaternion");
      78          14 :   keys.addOutputComponent("i","default","the i component of the quaternion");
      79          14 :   keys.addOutputComponent("j","default","the j component of the quaternion");
      80          14 :   keys.addOutputComponent("k","default","the k component of the quaternion");
      81           7 : }
      82             : 
      83           4 : QuaternionBondProductMatrix::QuaternionBondProductMatrix(const ActionOptions&ao):
      84             :   Action(ao),
      85           4 :   ActionWithMatrix(ao)
      86             : {
      87           4 :   if( getNumberOfArguments()!=8 ) error("should be eight arguments to this action, 4 quaternion components and 4 matrices");
      88           4 :   unsigned nquat = getPntrToArgument(0)->getNumberOfValues();
      89          20 :   for(unsigned i=0; i<4; ++i) {
      90          16 :     Value* myarg=getPntrToArgument(i); myarg->buildDataStore();
      91          16 :     if( myarg->getRank()!=1 ) error("first four arguments to this action should be vectors");
      92          16 :     if( (myarg->getPntrToAction())->getName()!="QUATERNION_VECTOR" ) error("first four arguments to this action should be quaternions");
      93          16 :     std::string mylab=getPntrToArgument(i)->getName(); std::size_t dot=mylab.find_first_of(".");
      94          24 :     if( i==0 && mylab.substr(dot+1)!="w" ) error("quaternion arguments are in wrong order");
      95          24 :     if( i==1 && mylab.substr(dot+1)!="i" ) error("quaternion arguments are in wrong order");
      96          24 :     if( i==2 && mylab.substr(dot+1)!="j" ) error("quaternion arguments are in wrong order");
      97          24 :     if( i==3 && mylab.substr(dot+1)!="k" ) error("quaternion arguments are in wrong order");
      98             :   }
      99           4 :   std::vector<unsigned> shape( getPntrToArgument(4)->getShape() );
     100          20 :   for(unsigned i=4; i<8; ++i) {
     101             :     Value* myarg=getPntrToArgument(i);
     102          16 :     if( myarg->getRank()!=2 ) error("second four arguments to this action should be matrices");
     103          16 :     if( myarg->getShape()[0]!=shape[0] || myarg->getShape()[1]!=shape[1] ) error("matrices should all have the same shape");
     104          16 :     if( myarg->getShape()[0]!=nquat ) error("number of rows in matrix should equal number of input quaternions");
     105          16 :     std::string mylab=getPntrToArgument(i)->getName(); std::size_t dot=mylab.find_first_of(".");
     106          24 :     if( i==5 && mylab.substr(dot+1)!="x" ) error("quaternion arguments are in wrong order");
     107          24 :     if( i==6 && mylab.substr(dot+1)!="y" ) error("quaternion arguments are in wrong order");
     108          24 :     if( i==7 && mylab.substr(dot+1)!="z" ) error("quaternion arguments are in wrong order");
     109             :   }
     110           8 :   addComponent( "w", shape ); componentIsNotPeriodic("w");
     111           8 :   addComponent( "i", shape ); componentIsNotPeriodic("i");
     112           8 :   addComponent( "j", shape ); componentIsNotPeriodic("j");
     113           8 :   addComponent( "k", shape ); componentIsNotPeriodic("k");
     114           4 :   done_in_chain=true; nderivatives = buildArgumentStore(0);
     115             : 
     116           4 :   std::string headstr=getFirstActionInChain()->getLabel(); stored.resize( getNumberOfArguments() );
     117          36 :   for(unsigned i=0; i<getNumberOfArguments(); ++i) stored[i] = getPntrToArgument(i)->ignoreStoredValue( headstr );
     118           4 : }
     119             : 
     120          32 : unsigned QuaternionBondProductMatrix::getNumberOfDerivatives() {
     121          32 :   return nderivatives;
     122             : }
     123             : 
     124          96 : unsigned QuaternionBondProductMatrix::getNumberOfColumns() const {
     125          96 :   const ActionWithMatrix* am=dynamic_cast<const ActionWithMatrix*>( getPntrToArgument(4)->getPntrToAction() );
     126          96 :   plumed_assert( am ); return am->getNumberOfColumns();
     127             : }
     128             : 
     129           0 : void QuaternionBondProductMatrix::setupForTask( const unsigned& task_index, std::vector<unsigned>& indices, MultiValue& myvals ) const {
     130           0 :   unsigned start_n = getPntrToArgument(4)->getShape()[0], size_v = getPntrToArgument(4)->getShape()[1];
     131           0 :   if( indices.size()!=size_v+1 ) indices.resize( size_v+1 );
     132           0 :   for(unsigned i=0; i<size_v; ++i) indices[i+1] = start_n + i;
     133             :   myvals.setSplitIndex( size_v + 1 );
     134           0 : }
     135             : 
     136      381366 : void QuaternionBondProductMatrix::performTask( const std::string& controller, const unsigned& index1, const unsigned& index2, MultiValue& myvals ) const {
     137      381366 :   unsigned ind2=index2;
     138      381366 :   if( index2>=getPntrToArgument(0)->getShape()[0] ) ind2 = index2 - getPntrToArgument(0)->getShape()[0];
     139             : 
     140      381366 :   std::vector<double> quat(4), bond(4), quatTemp(4);
     141      381366 :   std::vector<Tensor4d> dqt(2); //dqt[0] -> derivs w.r.t quat [dwt/dw1 dwt/di1 dwt/dj1 dwt/dk1]
     142             :   //[dit/dw1 dit/di1 dit/dj1 dit/dk1] etc, and dqt[1] is w.r.t the vector-turned-quaternion called bond
     143             : 
     144             :   // Retrieve the quaternion
     145     1906830 :   for(unsigned i=0; i<4; ++i) quat[i] = getArgumentElement( i, index1, myvals );
     146             : 
     147             :   // Retrieve the components of the matrix
     148      381366 :   double weight = getElementOfMatrixArgument( 4, index1, ind2, myvals );
     149     1525464 :   for(unsigned i=1; i<4; ++i) bond[i] = getElementOfMatrixArgument( 4+i, index1, ind2, myvals );
     150             : 
     151             :   // calculate normalization factor
     152      381366 :   bond[0]=0.0;
     153      381366 :   double normFac = 1/sqrt(bond[1]*bond[1] + bond[2]*bond[2] + bond[3]*bond[3]);
     154      381366 :   if (bond[1] == 0.0 && bond[2]==0.0 && bond[3]==0) normFac=1; //just for the case where im comparing a quat to itself, itll be 0 at the end anyway
     155             :   double normFac3 = normFac*normFac*normFac;
     156             :   //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
     157             : 
     158             : 
     159             : 
     160      381366 :   std::vector<double> quat_conj(4);
     161      381366 :   quat_conj[0] = quat[0]; quat_conj[1] = -1*quat[1]; quat_conj[2] = -1*quat[2]; quat_conj[3] = -1*quat[3];
     162             :   //make a conjugate of q1 my own sanity
     163             : 
     164             : 
     165             : 
     166             : 
     167             : //q1_conj * r first, while keep track of derivs
     168             :   double pref=1;
     169             :   double conj=1;
     170             :   double pref2=1;
     171             :   //real part of q1*q2
     172             : 
     173     1906830 :   for(unsigned i=0; i<4; ++i) {
     174     1525464 :     if( i>0 ) {pref=-1; conj=-1; pref2=-1;}
     175     1525464 :     quatTemp[0]+=pref*quat_conj[i]*bond[i];
     176     1525464 :     dqt[0](0,i) = conj*pref*bond[i];
     177     1525464 :     dqt[1](0,i) = pref2*quat_conj[i];
     178             :     //addDerivativeOnVectorArgument( false, 0, i, index1, conj*pref*bond[i], myvals );
     179             :     //addDerivativeOnVectorArgument( false, 0, 4+i, ind2, conj*pref*quat[i], myvals );
     180             :   }
     181             :   //i component
     182             :   pref=1;
     183             :   conj=1;
     184             :   pref2=1;
     185             : 
     186     1906830 :   for (unsigned i=0; i<4; i++) {
     187     1525464 :     if(i==3) pref=-1;
     188             :     else pref=1;
     189     1525464 :     if(i==2) pref2=-1;
     190             :     else pref2=1;
     191     1525464 :     if (i>0) conj=-1;
     192             : 
     193     1525464 :     quatTemp[1]+=pref*quat_conj[i]*bond[(5-i)%4];
     194     1525464 :     dqt[0](1,i) =conj*pref*bond[(5-i)%4];
     195     1525464 :     dqt[1](1,i) = pref2*quat_conj[(5-i)%4];
     196             :     //addDerivativeOnVectorArgument( false, 1, i, index1, conj*pref*bond[(5-i)%4], myvals );
     197             :     //addDerivativeOnVectorArgument( false, 1, 4+i, ind2, conj*pref*quat[i], myvals );
     198             :   }
     199             : 
     200             :   //j component
     201             :   pref=1;
     202             :   pref2=1;
     203             :   conj=1;
     204             : 
     205     1906830 :   for (unsigned i=0; i<4; i++) {
     206     1525464 :     if(i==1) pref=-1;
     207             :     else pref=1;
     208     1525464 :     if (i==3) pref2=-1;
     209             :     else pref2=1;
     210     1525464 :     if (i>0) conj=-1;
     211             : 
     212     1525464 :     quatTemp[2]+=pref*quat_conj[i]*bond[(i+2)%4];
     213     1525464 :     dqt[0](2,i)=conj*pref*bond[(i+2)%4];
     214     1525464 :     dqt[1](2,i)=pref2*quat_conj[(i+2)%4];
     215             :     //addDerivativeOnVectorArgument( false, 2, i, index1, conj*pref*bond[(i+2)%4], myvals );
     216             :     //addDerivativeOnVectorArgument( false, 2, 4+i, ind2, conj*pref*quat[i], myvals );
     217             :   }
     218             : 
     219             :   //k component
     220             :   pref=1;
     221             :   pref2=1;
     222             :   conj=1;
     223             : 
     224     1906830 :   for (unsigned i=0; i<4; i++) {
     225     1525464 :     if(i==2) pref=-1;
     226             :     else pref=1;
     227     1525464 :     if(i==1) pref2=-1;
     228             :     else pref2=1;
     229     1525464 :     if(i>0) conj=-1;
     230     1525464 :     quatTemp[3]+=pref*quat_conj[i]*bond[(3-i)];
     231     1525464 :     dqt[0](3,i)=conj*pref*bond[3-i];
     232     1525464 :     dqt[1](3,i)= pref2*quat_conj[3-i];
     233             :     //addDerivativeOnVectorArgument( false, 3, i, index1, conj*pref*bond[3-i], myvals );
     234             :     //addDerivativeOnVectorArgument( false, 3, 4+i, ind2, conj*pref*quat[i], myvals );
     235             : 
     236             :   }
     237             : 
     238             : 
     239             : //now previous ^ product times quat again, not conjugated
     240             :   //real part of q1*q2
     241      381366 :   double tempDot=0,wf=0,xf=0,yf=0,zf=0;
     242             :   pref=1;
     243             :   pref2=1;
     244     1906830 :   for(unsigned i=0; i<4; ++i) {
     245     1525464 :     if( i>0 ) {pref=-1; pref2=-1;}
     246     1525464 :     myvals.addValue( getConstPntrToComponent(0)->getPositionInStream(), normFac*pref*quatTemp[i]*quat[i] );
     247             :     wf+=normFac*pref*quatTemp[i]*quat[i];
     248     1525464 :     if( doNotCalculateDerivatives() ) continue ;
     249     1525464 :     tempDot=(dotProduct(Vector4d(quat[0],-quat[1],-quat[2],-quat[3]), dqt[0].getCol(i)) + pref2*quatTemp[i])*normFac;
     250     1525464 :     addDerivativeOnVectorArgument( stored[i], 0, i,   index1, tempDot, myvals);
     251             :   }
     252             :   //had to split because bond's derivatives depend on the value of the overall quaternion component
     253             :   //addDerivativeOnMatrixArgument( false, 0, 4, index1, ind2, 0.0, myvals );
     254     1906830 :   for(unsigned i=0; i<4; ++i) {
     255     1525464 :     tempDot=dotProduct(Vector4d(quat[0],-quat[1],-quat[2],-quat[3]), dqt[1].getCol(i))*normFac;
     256     1525464 :     if (i!=0 )addDerivativeOnMatrixArgument( stored[4+i], 0, 4+i, index1, ind2, tempDot, myvals );
     257      381366 :     else addDerivativeOnMatrixArgument( stored[4+i], 0, 4+i, index1, ind2, 0.0, myvals );
     258             :   }
     259             : // for (unsigned i=0; i<4; ++i) {
     260             : //myvals.addValue( getConstPntrToComponent(0)->getPositionInStream(), 0.0 );
     261             : //if( doNotCalculateDerivatives() ) continue ;
     262             : //addDerivativeOnVectorArgument( false, 0, i,   index1, 0.0, myvals);
     263             : //addDerivativeOnVectorArgument( false, 0, 4+i, ind2, 0.0 ,  myvals);
     264             : //  }
     265             : //the w component should always be zero, barring some catastrophe, but we calculate it out anyway
     266             : 
     267             :   //i component
     268             :   pref=1;
     269             :   pref2=1;
     270     1906830 :   for (unsigned i=0; i<4; i++) {
     271     1525464 :     if(i==3) pref=-1;
     272             :     else pref=1;
     273     1525464 :     myvals.addValue( getConstPntrToComponent(1)->getPositionInStream(), normFac*pref*quatTemp[i]*quat[(5-i)%4]);
     274     1525464 :     xf+=normFac*pref*quatTemp[i]*quat[(5-i)%4];
     275     1525464 :     if(i==2) pref2=-1;
     276             :     else pref2=1;
     277     1525464 :     if( doNotCalculateDerivatives() ) continue ;
     278     1525464 :     tempDot=(dotProduct(Vector4d(quat[1],quat[0],quat[3],-quat[2]), dqt[0].getCol(i)) + pref2*quatTemp[(5-i)%4])*normFac;
     279     1525464 :     addDerivativeOnVectorArgument( stored[i], 1, i,   index1, tempDot, myvals);
     280             :   }
     281             :   //addDerivativeOnMatrixArgument( false, 1, 4, index1, ind2, 0.0, myvals );
     282             : 
     283     1906830 :   for(unsigned i=0; i<4; ++i) {
     284     1525464 :     tempDot=dotProduct(Vector4d(quat[1],quat[0],quat[3],-quat[2]), dqt[1].getCol(i))*normFac;
     285     1525464 :     if (i!=0) addDerivativeOnMatrixArgument( stored[4+i], 1, 4+i, index1, ind2, tempDot+(-bond[i]*normFac*normFac*xf), myvals );
     286      381366 :     else  addDerivativeOnMatrixArgument( stored[4+i], 1, 4+i, index1, ind2, 0.0, myvals );
     287             : 
     288             :   }
     289             : 
     290             : 
     291             :   //j component
     292             :   pref=1;
     293             :   pref2=1;
     294     1906830 :   for (unsigned i=0; i<4; i++) {
     295     1525464 :     if(i==1) pref=-1;
     296             :     else pref=1;
     297     1525464 :     if (i==3) pref2=-1;
     298             :     else pref2=1;
     299             : 
     300     1525464 :     myvals.addValue( getConstPntrToComponent(2)->getPositionInStream(), normFac*pref*quatTemp[i]*quat[(i+2)%4]);
     301     1525464 :     yf+=normFac*pref*quatTemp[i]*quat[(i+2)%4];
     302     1525464 :     if( doNotCalculateDerivatives() ) continue ;
     303     1525464 :     tempDot=(dotProduct(Vector4d(quat[2],-quat[3],quat[0],quat[1]), dqt[0].getCol(i)) + pref2*quatTemp[(i+2)%4])*normFac;
     304     1525464 :     addDerivativeOnVectorArgument( stored[i], 2, i,   index1, tempDot, myvals);
     305             :   }
     306             :   //    addDerivativeOnMatrixArgument( false, 2, 4, index1, ind2,0.0   , myvals );
     307             : 
     308     1906830 :   for(unsigned i=0; i<4; ++i) {
     309     1525464 :     tempDot=dotProduct(Vector4d(quat[2],-quat[3],quat[0],quat[1]), dqt[1].getCol(i))*normFac;
     310     1525464 :     if (i!=0) addDerivativeOnMatrixArgument( stored[4+i], 2, 4+i, index1, ind2, tempDot+(-bond[i]*normFac*normFac*yf), myvals );
     311      381366 :     else  addDerivativeOnMatrixArgument( stored[4+i], 2, 4+i, index1, ind2, 0.0, myvals );
     312             : 
     313             : 
     314             :   }
     315             : 
     316             :   //k component
     317             :   pref=1;
     318             :   pref2=1;
     319     1906830 :   for (unsigned i=0; i<4; i++) {
     320     1525464 :     if(i==2) pref=-1;
     321             :     else pref=1;
     322     1525464 :     if(i==1) pref2=-1;
     323             :     else pref2=1;
     324             : 
     325     1525464 :     myvals.addValue( getConstPntrToComponent(3)->getPositionInStream(), normFac*pref*quatTemp[i]*quat[(3-i)]);
     326     1525464 :     zf+=normFac*pref*quatTemp[i]*quat[(3-i)];
     327     1525464 :     if( doNotCalculateDerivatives() ) continue ;
     328     1525464 :     tempDot=(dotProduct(Vector4d(quat[3],quat[2],-quat[1],quat[0]), dqt[0].getCol(i)) + pref2*quatTemp[(3-i)])*normFac;
     329     1525464 :     addDerivativeOnVectorArgument( stored[i], 3, i,   index1, tempDot, myvals);
     330             :   }
     331             :   //addDerivativeOnMatrixArgument( false, 3, 4, index1, ind2,  0.0 , myvals );
     332             : 
     333     1906830 :   for(unsigned i=0; i<4; ++i) {
     334     1525464 :     tempDot=dotProduct(Vector4d(quat[3],quat[2],-quat[1],quat[0]), dqt[1].getCol(i))*normFac;
     335     1525464 :     if (i!=0) addDerivativeOnMatrixArgument( stored[4+i], 3, 4+i, index1, ind2, tempDot+(-bond[i]*normFac*normFac*zf), myvals );
     336      381366 :     else addDerivativeOnMatrixArgument( stored[4+i], 3, 4+i, index1, ind2, 0.0, myvals );
     337             : 
     338             : 
     339             :   }
     340      381366 :   if( doNotCalculateDerivatives() ) return ;
     341             : 
     342     1906830 :   for(unsigned outcomp=0; outcomp<4; ++outcomp) {
     343     1525464 :     unsigned ostrn = getConstPntrToComponent(outcomp)->getPositionInStream();
     344     7627320 :     for(unsigned i=4; i<8; ++i) {
     345             :       bool found=false;
     346     6101856 :       for(unsigned j=4; j<i; ++j) {
     347     4576392 :         if( arg_deriv_starts[i]==arg_deriv_starts[j] ) { found=true; break; }
     348             :       }
     349     6101856 :       if( found || !stored[i] ) continue;
     350             : 
     351             :       unsigned istrn = getPntrToArgument(i)->getPositionInStream();
     352    24407424 :       for(unsigned k=0; k<myvals.getNumberActive(istrn); ++k) {
     353    22881960 :         unsigned kind=myvals.getActiveIndex(istrn,k); myvals.updateIndex( ostrn, kind );
     354             :       }
     355             :     }
     356             :   }
     357             : }
     358             : 
     359        1614 : void QuaternionBondProductMatrix::runEndOfRowJobs( const unsigned& ival, const std::vector<unsigned> & indices, MultiValue& myvals ) const {
     360        1614 :   if( doNotCalculateDerivatives() || !matrixChainContinues() ) return ;
     361             : 
     362        8070 :   for(unsigned j=0; j<getNumberOfComponents(); ++j) {
     363        6456 :     unsigned nmat = getConstPntrToComponent(j)->getPositionInMatrixStash(), nmat_ind = myvals.getNumberOfMatrixRowDerivatives( nmat );
     364             :     std::vector<unsigned>& matrix_indices( myvals.getMatrixRowDerivativeIndices( nmat ) ); unsigned ntwo_atoms = myvals.getSplitIndex();
     365             :     // Quaternion
     366       32280 :     for(unsigned k=0; k<4; ++k) { matrix_indices[nmat_ind] = arg_deriv_starts[k] + ival; nmat_ind++; }
     367             :     // Loop over row of matrix
     368       32280 :     for(unsigned n=4; n<8; ++n) {
     369             :       bool found=false;
     370       25824 :       for(unsigned k=4; k<n; ++k) {
     371       19368 :         if( arg_deriv_starts[k]==arg_deriv_starts[n] ) { found=true; break; }
     372             :       }
     373       25824 :       if( found ) continue;
     374             :       unsigned istrn = getPntrToArgument(n)->getPositionInMatrixStash();
     375             :       std::vector<unsigned>& imat_indices( myvals.getMatrixRowDerivativeIndices( istrn ) );
     376     4660320 :       for(unsigned k=0; k<myvals.getNumberOfMatrixRowDerivatives( istrn ); ++k) matrix_indices[nmat_ind + k] = arg_deriv_starts[n] + imat_indices[k];
     377        6456 :       nmat_ind += myvals.getNumberOfMatrixRowDerivatives( getPntrToArgument(4)->getPositionInMatrixStash() );
     378             :     }
     379             :     myvals.setNumberOfMatrixRowDerivatives( nmat, nmat_ind );
     380             :   }
     381             : }
     382             : 
     383             : }
     384             : }

Generated by: LCOV version 1.16