solvate_atom.m

Contents

Function arguments

Dependencies

Version

2.11

Contact

Please report problems/bugs to michael.holmboe@umu.se

Examples

function SOL = solvate_atom(limits,density,r,maxsol,varargin)

% Solvent shell thickness
if strcmpi(maxsol,'shell10')
    shellthickness=10;
elseif strcmpi(maxsol,'shell15')
    shellthickness=15;
elseif strcmpi(maxsol,'shell20')
    shellthickness=20;
elseif strcmpi(maxsol,'shell25')
    shellthickness=25;
elseif strcmpi(maxsol,'shell30')
    shellthickness=30;
elseif strcmpi(maxsol,'shell5')
    shellthickness=5;
elseif strcmpi(maxsol,'shell4')
    shellthickness=4;
elseif strcmpi(maxsol,'shell3')
    shellthickness=3;
elseif strcmpi(maxsol,'shell2')
    shellthickness=2;
elseif strncmpi(maxsol,'shell',5)
    shellthickness=10;
end

if numel(limits)==1
    limits(4:6)=limits(1);
    limits(1:3)=0;
    Lx=limits(4);
    Ly=limits(5);
    Lz=limits(6);
elseif numel(limits)==3
    Lx=limits(1);
    Ly=limits(2);
    Lz=limits(3);
    limits(4)=limits(1);
    limits(5)=limits(2);
    limits(6)=limits(3);
    limits(1:3)=0;
elseif numel(limits)==6
    Lx=limits(4)-limits(1);
    Ly=limits(5)-limits(2);
    Lz=limits(6)-limits(3);
elseif numel(limits)==9
    Lx=limits(1);
    Ly=limits(2);
    Lz=limits(3);
    limits(4)=limits(1);
    limits(5)=limits(2);
    limits(6)=limits(3);
    limits(1:3)=0;
end

% Old way of doing it...
% SOL=import_atom_gro(strcat('spc864_',num2str(density,'%3.2f'),'.gro')); % I was fastest... [2 2 1]*216.gro

if nargin == 4
    solute_atom=[];
else
    solute_atom=varargin{1};
end

if nargin>5
    watermodel=varargin(2);
    if iscell(watermodel)
        assignin('caller','watermodel',watermodel)
        watermodel=char(watermodel{1});
    end
    if strncmpi(watermodel,'spc_ice',7)
        SOL=import_atom_gro('96spc_hex_ice_h.gro');
        pause(1)
        disp('Adding hexagonal spc ice!!!')
    elseif strncmpi(watermodel,'tip4p_ice',9)
        SOL=import_atom_gro('96tip4p_hex_ice_h.gro');
        pause(1)
        disp('Adding hexagonal tip4p ice!!!')
    elseif strncmpi(watermodel,'spce',4)
        SOL=import_atom_gro('864_spce.gro');
        disp('Adding spc/e!!!')
    elseif strncmpi(watermodel,'spc',3)
        SOL=import_atom_gro('864_spc.gro');
        disp('Adding spc!!!')
    elseif strncmpi(watermodel,'tip3p',5)
        SOL=import_atom_gro('864_tip3p.gro');
        disp('Adding tip3p!!!')
    elseif strncmpi(watermodel,'tip4p',5)
        SOL=import_atom_gro('864_tip4p.gro');
        disp('Adding tip4p!!!')
    elseif strncmpi(watermodel,'tip5p',5)
        SOL=import_atom_gro('864_tip5p.gro');
        disp('Adding tip5p!!!')
    elseif strncmpi(watermodel,'swm4',4)
        SOL=import_atom_gro('864_swm4_ndp.gro');
        disp('Adding swm4_ndp!!!')
    elseif strncmpi(watermodel,'custom',5)
        disp('You are using your own solvent, you must be brave')
        SOL=varargin{3};
        if nargin>7
            Box_dim=varargin{4};
            if numel(Box_dim)>3
                disp('Custom solvent boxes must be orthogonal, i.e. numel(Box_dim)==3')
                pause
            end
        end
    end
else
    SOL=import_atom_gro('864_spc.gro');
    disp('Adding spc / spc/e!!!')
end

atomsperSOL=sum([SOL.molid]==1);

SOL=scale_atom(SOL,Box_dim,[1 1 1]./density,'all');

nx=ceil(Lx/Box_dim(1))
ny=ceil(Ly/Box_dim(2))
nz=ceil(Lz/Box_dim(3))
SOL=replicate_atom(SOL,Box_dim,[nx ny nz],'xzy');
disp('Replicated n times');
nx*ny*nz;

if (limits(1)+limits(2)+limits(3)) ~= 0
    disp('Translating the solvent box');
    SOL=translate_atom(SOL,[limits(1) limits(2) limits(3)],'all');
end

disp('nSOL before merge');
size(SOL,2)/atomsperSOL

if size(solute_atom,2) > 0
    if size(SOL,2) > 10000 || size(solute_atom,2) > 10000
        nSOL_block=size(SOL,2)/(nx*ny*nz);
        SOL_count=1;SOL_merged=[];count=1;
        while SOL_count<size(SOL,2)
            SOL_block= SOL(SOL_count:SOL_count+nSOL_block-1);
            SOL_block = merge_atom(solute_atom,limits(4:6)-.2,SOL_block,'molid','H',[r-.4 r]); % Can shell be implemented here instead?
            SOL_merged = [SOL_merged SOL_block];
            SOL_count=SOL_count+nSOL_block;
            disp('Number of solvent molecules...');
            count=count+1;
            size(SOL_merged,2)/atomsperSOL
        end
        SOL=SOL_merged;
    else
        SOL = merge_atom(solute_atom,limits(4:6)-.2,SOL,'molid','Hw',[r-.4 r]); % Can shell be implemented here instead?
    end
else
    SOL=slice_atom(SOL,[limits(1) limits(2) limits(3) limits(4:6)-.4],0);
end

SOL=update_atom(SOL);

% Randomize the order of the SOL molecules, and check for 'max' or 'shell' option
nSOL=size(SOL,2);
if iscellstr({maxsol}) == 1
    if strncmpi(maxsol,'max',3)
        maxsol=nSOL/atomsperSOL;
    elseif strncmpi(maxsol,'shell',5)
        disp('Will solvate a shell around the solute molecule')
        nSolute=size(solute_atom,2);
        if (size(SOL,2)+size(solute_atom,2))>50000
            dist_matrix = cell_list_dist_matrix_atom(update_atom({solute_atom SOL}),Box_dim);
            dist_matrix(dist_matrix==0)=2*shellthickness; % Set some high dummy value
        else
            dist_matrix = dist_matrix_atom(update_atom({solute_atom SOL}),Box_dim);
        end
        ind=[];
        for i=1:size(SOL,2) % Vectorize this!!!
            if min(dist_matrix(nSolute+i,1:nSolute))>shellthickness
                ind=[ind i];
            end
        end
        molid=unique([SOL(intersect([SOL.index],ind)).molid]);
        rm_ind = ismember([SOL.molid],molid);
        SOL(rm_ind)=[];
        nSOL=size(SOL,2);
        maxsol=size(SOL,2)/atomsperSOL;
        SOL=update_atom(SOL);
    end
end
rand_molid=randperm(nSOL/atomsperSOL);
if maxsol>size(rand_molid,2)
    disp('You have tried to add too many solvent molecules for the given region')
end
disp('Number of maximum solvent molecules possible')
size(rand_molid,2)
disp('Number of solvent molecules requested')
maxsol

rand_molid=rand_molid(1:maxsol);

rand_index=ismember([SOL.molid],rand_molid);
SOL=SOL(rand_index);

% Delete water molecules if not using the <maxsol> option
if iscellstr({maxsol}) == 0
    if atomsperSOL*maxsol > size(SOL,2)
        disp('Ooops, you asked for too much solvent...')
        maxsol
        disp('Maximum number of solvent molecules allowed without changing the density or rmin is:')
        size(SOL,2)/atomsperSOL
        SOL=SOL(1:atomsperSOL*maxsol);
    else
        % Use randperm instead... ?
        SOL=SOL(1:atomsperSOL*maxsol);
    end
end
SOL=update_atom(SOL);

disp('nSOL after merge')
size(SOL,2)/atomsperSOL

assignin('caller','SOL',SOL);
assignin('caller','limits',limits);