            Common Tangent Line Method


- Base Idea (with some thermodynamics)

Free energy is 4th order curve and when proper x-y axis variable are used, 2 points where common tangent line contacts free energy curve satisfy thermodynamic equilibrium condition.
As a result, if we can find common tangent line, then we can find equilibrium points.
This method doesn't need initial guess to draw a phase diagram and shows a way to automatic parameter-fitting.

In pure fluid system, molecular number 'n' versus free energy 'A or G' graph is used.
In binary system, mole fraction 'phi' versus free energy per mer 'g or a' graph is used.
Because of my ignorance about thermodynamics, I have nothing to mention about the systems which have more than 2 elements.


- Brief explanation of code

'func_common_tangent' in 'comtan.c' is the main implementation of common tangent method.
func_common_tangent use free energy funtion(p_func_free_energy, 4th order) and differential function( or slope) of free energy(p_func_free_slope, 3rd order) to find 2 points where common tangent line contacts free energy curve, which are equilibrium points.

In pure system,
  p_func_free_energy is free energy of the system (G : Gibbs or A : Helmholtz) in the function of 'molecule number n'.
  p_func_free_slope is chemical potential in the function of "molecular number n".
  ! Important !
  Other variables like densities(rhotilda, rho, rho_r) or mole fraction(phi) should be converted to 'molecule number n'.

In binary system,
  p_func_free_energy is free energy per segment or per mer (g : Gibbs free energy per mer. Helmholtz free energy per mer is also applicable.) in the function of "mole fraction phi".
  p_func_free_slope is the partial differential of g against phi in the function of "mole fraction phi". (partial differential g / partial differential phi) 
  ! Important !
  Other variables like densities(rhotilda, rho, rho_r) or molecular number should be converted to "mole fraction phi"

  p_func_free_energy : pointer for free energy function
  p_func_free_slope : pointer for differential(or slope) function of free energy
  p_a_arg_fe : pointer for a_arg_fe which is the array of arguments for free energy function.
               arg_fe[0] is "molecular number n" for pure system
                        and "mole fraction phi" for bianry system
                        and used by func_common_tangent.
               Other part except [0] of a_arg_fe is transfered to free energy function as it is given.
  p_a_arg_fs : pointer for a_arg_fs which is the array of arguments for free energy slope function.
               arg_fs[0] is  "molecular number n" for pure system
                        and "mole fraction phi" for bianry system
                        and used by func_common_tangent.
               Other part except [0] of a_arg_fs is transfered to free energy slope function as it is given.
  p_a_arg_ct : pointer for a_arg_ct which is the array of arguments for func_common_tangent itself.
  p_i_stats :  pointer of int variable which tells the solution is successfully found or not.
               ( *p_i_stats = 0 : solution calculation failed.
                 *p_i_stats = 1 : solution calculation succeeded. )
							 	
  a_arg_ct is set as following.
          a_arg_ct[0] = d_sol_low[_pre]
             : when transferred from main routine to common_tangent, this is previous solution.
               when transferred from common_tangent to main routine, this is the calculated solution.
          a_arg_ct[1] = d_sol_high[_pre]
             : when transferred from main routine to common_tangent, this is previous solution.
               when transferred from common_tangent to main routine, this is the calculated solution.
          a_arg_ct[2] = d_low_limit ( usually small value like 1.e-10(for n) or 1.e-40(for phi) )
          a_arg_ct[3] = d_high_limit ( for phi, usually ( 1.0 - 1.e-10 ) is used.
              
  The limit value of "molecular number n" can be calculated from density or packing fraction variables.
  For example, "0 < rhotilda < 1" (LF),
               "0 < eta < 0.76"(PHSC)

Source is best view when indent and tab size is set to '2'.


- Compiler

This code is compiled and tested with following compilers.

GCC variants
  - DJGPP
  - MinGW + MSys
  - Cygwin
Borland C++ 5.5
Microsoft Visual C++ 6.0

GCC on UNIX, Linux and other variants should have no problem compiling.


- Compile Trouble Shooting

General : If failure of finding 'comtan.h' occurs, check if the 'include' statement in 'PHSC_Draw.c' and the real path of 'comtan.h' matches.
Borland C++ 5.5 : Read the 'readme.txt' and do whatever it says. (e.g. Add path. Creat 'bcc32.cfg' and 'ilink32.cfg' in 'bin' directory.) And Reboot. Ignore compile warning.
Microsoft Visual C++ 6.0 : Run 'vcvars32.bat' first.
                 If 'Out of Environment' error occurs, increase the space for environment variables.
                   On MS-Windows 95, 98 and ME : Right-click the MS-DOS Prompt shortcut, and then click Properties. Click the Memory tab. In the Initial Environment box, set the initial environment size to 4,096 bytes. Click OK
                   On MS-Windows NT : Control Panel - System - Environment - Comspec - Increase the amount of environment space. 'ComSpec = <drive:\windir>\system32\cmd.exe /e:4096' 
                   On MS-Windows 2000 : Control Panel - Advanced - Environment Variables. - In the System variables, click ComSpec. - Increase the amount of environment space. 'ComSpec = <drive:\windir>\system32\cmd.exe /e:4096'
                   On MS-Windows XP : Sorry. Help yourself. Microsoft knowledge base can be helpful. Use keyword 'out of environment'.


- Calculation Trouble Shooting

If code compiles but doesn't run or stop during calculation.

1. Try smaller search increment(d_break, d_delta) in 'comtan.c'.
   Too small increment may slow down the calculation significantly.
   Proper search increment for each EOS is found by 'trial and error'.
   And, this is the weakest point of this code.
2. Modifyng low and high limit of searching area(a_arg_ct[2], a_arg_ct[3]) may solve the problem.


- Brief description of free C compilers for MS-Windows 

GCC variants
  GCC is a free C compiler. There is no restriction about source code. You can see, modify and distribute the source. But, you can not hide the source. It was orginally developed for UNIX, but these days they are ported to MS-Windows and other OSes.
  DJGPP(http://www.delorie.com/djgpp/) is a GCC port of MS-DOS and also runs on MS-Windows.
  MinGW(http://www.mingw.org) is a GCC port of MS-Windows. To use develpment utilities, MSys(http://www.mingw.org) is needed. MSys is a free UNIX shell emulation on MS-Windows.
  Cygwin(http://www.cygwin.com/) is a free UNIX on MS-Windows. Cygwin have compilers, nice GUI debugger and free X-windows.

Borland C++
  Borland C++ 5.5 is the core compiler for Borland C++ Builder and distributed at no charge.
  In my private test, Borland C++ is the fastest free C compiler for MS-Windows.
  You can download at Borland website(http://www.borland.com) with no charge.

Choice for development process
  - Cygwin
      Cygwin includes a nice GUI debugger 'insight' which makes debugging process easier.

Choice for calculation process
  - Borland C++ 5.5
      When code is stable and heavy calculation is performed, Borland C++ 5.5 is the best choice and DJGPP is the next because they gives high speed to save calculation time (as much as 60%).


- Etc
The driving force of existence of this code was my personal hatred of partial differentiation.
Whenever I have a new idea(e.g. replacing a term with a new one, removal of some assumption in derivation, ..) and want to check the correctness of my idea, I had to differentiate the free energy to draw the phase diagram.
If I(or anybody) can find common tangent line with 'free energy curve only', we can skip the error-prone process of 'differentiating the free energy' and can speed up the routine process of 'idea and check'(or trial and error).
I've tried free energy only algorithm, but numerical diffentiation didn't give accurate value, so the resulting error was unacceptable.
Anyway my initial trial took too long time to cover-up with no output and I was in a situation that I should submit some result or quit.
The result is this code which still needs differentiation process.
Anyway, this code remove the need of initial guess and make 'automated parameter optimization process' possible.
If someone have the code which can draw phase diagram with free energy only, I want to say him(or her) a word, 'Congratulations'.
