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 : }