LCOV - code coverage report
Current view: top level - liquid_crystal - FerroNematicOrder.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 29 30 96.7 %
Date: 2025-12-04 11:19:34 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2025 of Alexander Humeniuk.
       3             : 
       4             :    This file is part of the liquid_crystal plumed module.
       5             : 
       6             :    The liquid_crystal plumed module is free software: you can redistribute it and/or modify
       7             :    it under the terms of the GNU Lesser General Public License as published by
       8             :    the Free Software Foundation, either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    The liquid_crystal plumed module is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU Lesser General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU Lesser General Public License
      17             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      18             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      19             : #include "core/ActionShortcut.h"
      20             : #include "core/ActionRegister.h"
      21             : #include "multicolvar/MultiColvarShortcuts.h"
      22             : 
      23             : using namespace PLMD::multicolvar;
      24             : 
      25             : namespace PLMD {
      26             : namespace liquid_crystal {
      27             : 
      28             : //+PLUMEDOC COLVAR FERRONEMATIC_ORDER
      29             : /*
      30             : Calculate the ferronematic order parameter.
      31             : 
      32             : The ferronematic order parameter P depends on the relative orientations of the molecular
      33             : axes. If the axes all point into the same direction, giving rise to a net polarization if
      34             : the molecules have permanent dipole moments, P is close to 1. If the molecular axes are
      35             : oriented isotropically or are aligned antiparallel so that there is no net polarization,
      36             : P is close 0.
      37             : 
      38             : The nematic and ferronematic order parameters can be used to distinguish the isotropic,
      39             : nematic and ferronematic phases of liquid crystals.
      40             : 
      41             : $P$ is length of the average of the molecular axes ($\hat{u}_i$ for $i=1,\ldots,N$)
      42             : $$
      43             : P = \vert \frac{1}{N} \sum_{i=1}^N \hat{u}_i \vert
      44             : $$
      45             : Since the molecular axes are unit vectors, P ranges from a minimum of 0 to a maximum of 1.
      46             : 
      47             : By adding a bias to the ferronematic order parameter, one can drive a liquid crystal from the
      48             : isotropic to the ferronematic phase.
      49             : 
      50             : The axis of a rod-like molecule is defined as the distance vector between two atoms,
      51             : it points from the tail atom to the head atom.
      52             : 
      53             : ```plumed
      54             : # Assume there are three molecules with 20 atoms each.
      55             : # In the first molecule the molecular axis vector points from atom 1 to atom 20,
      56             : # in the second molecule it points from atom 21 to atom 40
      57             : # and in the third from atom 41 to atom 60.
      58             : # The ferronematic order parameter for the three molecules is computed as
      59             : P: FERRONEMATIC_ORDER MOLECULE_STARTS=1,21,41 MOLECULE_ENDS=20,40,60
      60             : PRINT FILE=colvar ARG=P
      61             : 
      62             : # Add a bias to the ferronematic order parameter P.
      63             : BIASVALUE ARG=P
      64             : ```
      65             : 
      66             : */
      67             : //+ENDPLUMEDOC
      68             : 
      69             : class FerroNematicOrder : public ActionShortcut {
      70             : public:
      71             :   static void registerKeywords(Keywords& keys);
      72             :   explicit FerroNematicOrder(const ActionOptions&);
      73             : };
      74             : 
      75             : PLUMED_REGISTER_ACTION(FerroNematicOrder,"FERRONEMATIC_ORDER")
      76             : 
      77           4 : void FerroNematicOrder::registerKeywords(Keywords& keys) {
      78           4 :   ActionShortcut::registerKeywords( keys );
      79           4 :   keys.add("atoms","MOLECULE_STARTS","The atoms where the molecular axis starts.");
      80           4 :   keys.add("atoms","MOLECULE_ENDS","The atoms where the molecular axis ends.");
      81           8 :   keys.setValueDescription("scalar","the modulus of the average vector");
      82           4 :   keys.needsAction("DISTANCE");
      83           4 :   keys.needsAction("CUSTOM");
      84           4 :   keys.needsAction("MEAN");
      85           4 : }
      86             : 
      87           2 : FerroNematicOrder:: FerroNematicOrder(const ActionOptions& ao):
      88             :   Action(ao),
      89           2 :   ActionShortcut(ao) {
      90             :   // Fetch indices of atoms that define the tails and the heads of the molecular axes.
      91             :   std::vector<std::string> starts, ends;
      92           2 :   MultiColvarShortcuts::parseAtomList("MOLECULE_STARTS",starts,this);
      93           4 :   MultiColvarShortcuts::parseAtomList("MOLECULE_ENDS",ends,this);
      94             : 
      95           2 :   if( starts.size()!=ends.size() )
      96           0 :     error(
      97             :       "Mismatched numbers of atoms specified to MOLECULE_STARTS and MOLECULE_ENDS keywords. "
      98             :       "The molecular axes are specified by pairs of atoms."
      99             :     );
     100             : 
     101           2 :   std::string dlist = "";
     102           7 :   for(unsigned i=0; i<starts.size(); ++i) {
     103             :     std::string num;
     104           5 :     Tools::convert( i+1, num );
     105          10 :     dlist += " ATOMS" + num + "=" + starts[i] + "," + ends[i];
     106             :   }
     107             : 
     108           2 :   std::string L = getShortcutLabel();
     109             :   // Calculate the lengths of the distance vectors
     110             :   //   d: DISTANCE ATOMS1=1,2 ATOMS2=3,4 ...
     111           4 :   readInputLine( L + "_dvals: DISTANCE" + dlist );
     112             :   // Calculate the molecular axes of the molecules
     113             :   //   dc: DISTANCE COMPONENTS ATOMS1=1,2 ATOMS2=3,4 ...
     114           4 :   readInputLine( L + "_dvecs: DISTANCE COMPONENTS " + dlist );
     115             :   // Convert the molecular axes into unit vectors
     116             :   //   dux: CUSTOM ARG=dc.x,d FUNC=x/y PERIODIC=NO
     117             :   //   duy: CUSTOM ARG=dc.y,d FUNC=x/y PERIODIC=NO
     118             :   //   duz: CUSTOM ARG=dc.z,d FUNC=x/y PERIODIC=NO
     119           4 :   readInputLine( L + "_dux: CUSTOM ARG=" + L + "_dvecs.x," + L + "_dvals FUNC=x/y PERIODIC=NO");
     120           4 :   readInputLine( L + "_duy: CUSTOM ARG=" + L + "_dvecs.y," + L + "_dvals FUNC=x/y PERIODIC=NO");
     121           4 :   readInputLine( L + "_duz: CUSTOM ARG=" + L + "_dvecs.z," + L + "_dvals FUNC=x/y PERIODIC=NO");
     122             :   // Now calculate the average of the molecular axes
     123             :   //   mux: MEAN ARG=dux PERIODIC=NO
     124             :   //   muy: MEAN ARG=duz PERIODIC=NO
     125             :   //   muz: MEAN ARG=dyz PERIODIC=NO
     126           4 :   readInputLine( L + "_mux: MEAN ARG=" + L + "_dux PERIODIC=NO");
     127           4 :   readInputLine( L + "_muy: MEAN ARG=" + L + "_duy PERIODIC=NO");
     128           4 :   readInputLine( L + "_muz: MEAN ARG=" + L + "_duz PERIODIC=NO");
     129             :   // Compute the ferronematic order parameter
     130             :   //   p: CUSTOM ARG=mux,muy,muz FUNC=sqrt(x*x+y*y+z*z) PERIODIC=NO
     131           4 :   readInputLine( L + ": CUSTOM ARG=" + L + "_mux," + L + "_muy," + L + "_muz FUNC=sqrt(x*x+y*y+z*z) PERIODIC=NO");
     132           2 : }
     133             : 
     134             : }
     135             : }

Generated by: LCOV version 1.16