clear
clc

%% MATLAB version of the PB solver

% THIS CODE IS BASED ON THE HOLST ARTICLE AND THE APBS ALGORITHM. IT
% BASICALLY SOLVES THE LINEARIZED PB EQUATION AND THEN SAVE THE SOLUTION 
% AND THE CHARGE DISTRIBUTION MAPS IN DX FORMAT. 


% WARNING!!!!!!!!!!!!!!! BEFORE USING IT: 

% FIRST STEP:

% PLEASE, CREATE A FOLDER "Matlab_Input_Files" SOMEWHERE CONTAINING THE FOLLOWING
% INPUT FILES:
% THE PQR FILE.
% THE THREE DX FILES CORRESPONDING TO THE SHIFTED DIELECTRIC COEFFICIENTS
% AS GENERATED BY THE APBS CODE.
% THE DX FILE CORRESPONDING TO THE KAPPA COEFFICIENTS AS GENERATED BY THE
% APBS CODE.
% THE .INM FILE WHICH IS THE MAIN INPUT FILE OF THIS CODE.

%SECOND STEP:

% YOU HAVE TO CREATE THE .INM INPUT FILE

% The .inm file parsing is strict.
% input must contain the value of these parameters in exactly this order in a column:
% dime   
% glen   
% T
% dielx_str
% diely_str
% dielz_str
% kappa_str
% pqr_str
% name_str

%|--example born.inm file--|
% 65 65 65               % Number of grid points (AS IN APBS CODE)
% 12 12 12              % in Amstrongs (AS IN APBS CODE)
% 298.15                    % Tempature in Kelvin
% born-dielx.dx       % Filename of input data
% born-diely.dx
% born-dielz.dx
% born-kappa.dx
% born-ion.pqr             (pqr file name)
% born_ion_model           (This is the subFoldername to be created into the current Directory 
                           % to save the four output files)
%|--------------------|
  
% THIRD STEP:
% PLEASE, ADD THE PATH OF THE PREVIOUS DIRECTORY TO THE MATLAB SEARCH PATH
% AS IT IS DONE IN THE EXAMPLE PROVIDED IN THE NEXT TWO LINES 

  MYPATH='/Users/mmarucho/DNA_solvation_regular_grid';
  addpath(MYPATH)

% FOURTH STEP:
% YOU HAVE TO CHANGE THE .INM INPUT FILE NAME IN THE 
% NEXT LINE OF THIS CODE BY THE ONE YOU HAVE PREVIOUSLY CREATED.
% AS AN EXAMPLE, WE USED DNA.inm AS THE INPUT FILE. 

  inputfile='DNA.inm';

% YOU ARE DONE. NOW YOU ARE READY TO USE THIS CODE!!!!!! THANKS !!!!

% CALLED MATLAB FILES: 
% read_inm.m (read the input file)
% data_parse.m (To read dx files and convert them to data arrays)
% BoundaryCondition.m (To evaluate the dirichlet boundary condition along the
% 6 faces)
% BuildA.m (construction of A matrix and b columm vector)
% dx_export.m (To convert data arrays to dx format)
% discretization.m (To spread the point-like charges around the nearest grid
% points.)

%% Part 1.  Read the data

% read the .inm file and display it in the matlab cmd

 [dime, glen, T, bulk, dielx_str, diely_str, dielz_str, kappa_str, pqr_str,nam_str] = read_inm(inputfile);

disp('Welcome!!!!!!....')
disp(' ')
disp('This code will calculate the approximate solution for ')
disp('the electrostatic potential for the....')
disp(nam_str)
disp(' ')
disp('Reading the input files')
% read the .dx files

% data_parse loads the file, and displays the reading ... message
%charge=data_parse('DNA-charge.dx', dime);
dielx=data_parse(dielx_str, dime);
diely=data_parse(diely_str, dime);
dielz=data_parse(dielz_str, dime);
kappa=data_parse(kappa_str, dime);


disp('Done!....')
disp(' ')

% find the spatial step sizes in each dimension h

for dimension=1:3
  h(dimension)=glen(dimension)/(dime(dimension)-1);  
end


%% Part 2.  solve A*pot=b

% Evaluation of Boundary Conditions
tic

disp('Calculating boundary condition....')


run BoundaryCondition

disp('Done!....')
disp(' ')
%Discretization charge density

disp('Generating the charge map....')


run discretization

disp('Done!....')
disp(' ')

rmin=[xmin ymin zmin];

% Prepare the Laplacian operator A and b

disp('Constructing the sparse matrix A....')

run BuildA

disp('Done!....')
disp(' ')

% Solve A*pot=b using the biconjugate gradients stabilized method

disp('Performing the LU decomposition....')

tolerance=0.25;
[L U]=luinc(A,tolerance);

disp('Done!....')
disp(' ')

disp('Solving the linear equation system using the')

disp('Biconjugated gradient method stabilized by LU matrices')


accuracy=10^-10;
max_iteration=800;
[pote,flag,relres,iter]=bicgstab(A,bb,accuracy, max_iteration,L,U);

if flag ~= 0
disp('The solver was reach the desired accuracy....') 
disp('please change the tolerance and or the')
disp('number of maximum iteration and try it again')
flag
iter
relres
return
end
error=relres
iteration_number=iter
disp('Done!....')
disp(' ')
% Add Boundary to Solution

potc=zeros(dime(1)-2,dime(2)-2,dime(3)-2);

for i=2:dime(1)-1
    for j=2:dime(2)-1
        for k=2:dime(3)-1
             pe=(k-2)*(dime(1)-2)*(dime(2)-2)+(j-2)*(dime(1)-2)+i-1;
             potc(i,j,k)=pote(pe);
        end
    end
end

MATLAB_pot=potB;

MATLAB_pot(2:dime(1)-1,2:dime(1)-1,2:dime(1)-1)=potc(2:dime(1)-1,2:dime(1)-1,2:dime(1)-1);

computing_time=toc

mkdir(nam_str)

%% Part 3: Write out the electrostatic potential in dx format
disp('Converting to dx format...')
dxformat=MATLAB_pot;
namefile='POTENTIAL (KT/e)';
outputfile=strcat(nam_str,'_MATLAB_Potential_Solution.dx');
run dx_export
disp(['the file ' outputfile ' was generated'])
movefile (outputfile, nam_str)
%
dxformat=charge;
namefile='CHARGE DENSITY (e/A^3)';
outputfile=strcat(nam_str,'_MATLAB_charge_density.dx');
run dx_export
disp(['the file ' outputfile ' was generated'])
movefile (outputfile, nam_str)
disp('Done!')
disp(' ')
%% Part 4: Generating the surface Plots

disp('Generating plots!....')

% surface defined by z=33
n=(dime(3)+1)/2;

%plotting the electrostatic potential solutions

name2= strcat(nam_str,'_MATLAB_Potential_solution');
plot2=surf(MATLAB_pot(:,:,n),'facecolor','interp');
saveas(plot2,name2,'fig');
disp(['the file ' name2 '.fig was generated'])
movefile (strcat(name2,'.fig'), nam_str)
saveas(plot2,name2,'jpg');
disp(['the file ' name2 '.jpg was generated'])
movefile (strcat(name2,'.jpg'), nam_str)
disp('Done!....')
disp(' ')

disp('Thanks for using our PB solver!!!!....')
%end
