LCOV - code coverage report
Current view: top level - src/78_effpot - m_fit_data.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 92.0 % 125 115
Test Date: 2026-09-20 15:27:41 Functions: 55.6 % 9 5

            Line data    Source code
       1              : !!****m* ABINIT/m_fit_data
       2              : !!
       3              : !! NAME
       4              : !! m_fit_data
       5              : !!
       6              : !! FUNCTION
       7              : !!
       8              : !! COPYRIGHT
       9              : !! Copyright (C) 2010-2026 ABINIT group (AM)
      10              : !! This file is distributed under the terms of the
      11              : !! GNU General Public Licence, see ~abinit/COPYING
      12              : !! or http://www.gnu.org/copyleft/gpl.txt .
      13              : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      14              : !!
      15              : !! SOURCE
      16              : 
      17              : 
      18              : #if defined HAVE_CONFIG_H
      19              : #include "config.h"
      20              : #endif
      21              : 
      22              : #include "abi_common.h"
      23              : 
      24              : module m_fit_data
      25              : 
      26              :  use defs_basis
      27              :  use m_errors
      28              :  use m_abicore
      29              : 
      30              :  use m_geometry,     only : metric
      31              : 
      32              :  implicit none
      33              : !!***
      34              : 
      35              : !!****t* m_fit_data/training_set_type
      36              : !! NAME
      37              : !! training_set_type
      38              : !!
      39              : !! FUNCTION
      40              : !! datatype for with all the information for the fit process
      41              : !! This structure contains all the information of the training set:
      42              : !!   - ntime
      43              : !!   - displacement
      44              : !!   - du_delta
      45              : !!   - strain
      46              : !!   - sqomega
      47              : !!   - ucvol
      48              : !!
      49              : !! SOURCE
      50              : 
      51              :  type, public :: training_set_type
      52              : 
      53              :    integer :: ntime
      54              : !    Number of time in the training set
      55              : 
      56              :    integer :: natom
      57              : !    Number of atoms in the training set
      58              : 
      59              :    real(dp), allocatable :: displacement(:,:,:)
      60              : !    displacement(3,natom,ntime)
      61              : !    displacement array, difference of the position in cartisian coordinates
      62              : !    between training set and reference
      63              : 
      64              :    real(dp), allocatable :: du_delta(:,:,:,:)
      65              : !    du_delta(6,3,natom,ntime)
      66              : !    du_delta array, variation of displacement wrt to the strain
      67              : 
      68              :    real(dp), allocatable :: strain(:,:)
      69              : !    strain(6,ntime)
      70              : !    strain array, strain in the training set
      71              : 
      72              :    real(dp), allocatable :: sqomega(:)
      73              : !    sqomega(ntime)
      74              : !    sqomega(itime) = (((ucvol(itime)**(-2.))* ((natom_sc)**(0.5)))**(-1.0/3.0))**2
      75              : 
      76              :    real(dp), allocatable :: ucvol(:)
      77              : !    ucvol(ntime)
      78              : !    ucvol array, volume of the cell in the training set
      79              : 
      80              :  end type training_set_type
      81              : 
      82              : !routine for training_set
      83              :  public :: training_set_init
      84              :  public :: training_set_free
      85              : !!***
      86              : 
      87              : !----------------------------------------------------------------------
      88              : 
      89              : !!****t* m_fit_data/fit_data_type
      90              : !! NAME
      91              : !! fit_data_type
      92              : !!
      93              : !! FUNCTION
      94              : !!
      95              : !! SOURCE
      96              : 
      97              :  type, public :: fit_data_type
      98              : 
      99              :    integer :: ntime
     100              : !   Number of time in the training set
     101              : 
     102              :    integer :: natom
     103              : !   Number of atoms in the training set
     104              : 
     105              :    real(dp),allocatable :: energy_diff(:)
     106              : !   energy(ntime)
     107              : !   Array with the diffence between energy from training set and energy from initial model.
     108              : !   The model constains only harmonic part
     109              : 
     110              :    real(dp),allocatable :: fcart_diff(:,:,:)
     111              : !   fcart_diff(3,natom,ntime)
     112              : !   Array with the diffence between cartesian forces from training set and forces from initial model.
     113              : !   The model constains only harmonic part
     114              : 
     115              :    real(dp),allocatable :: strten_diff(:,:)
     116              : !   strten_diff(6,ntime)
     117              : !   Array with the diffence between strain from training set and strain from initial model.
     118              : !   The model constains only harmonic part
     119              : 
     120              :    type(training_set_type) :: training_set
     121              : !    datatype with the information of the training set
     122              : 
     123              :  end type fit_data_type
     124              : 
     125              : !routine for fit_data
     126              :  public :: fit_data_compute
     127              :  public :: fit_data_init
     128              :  public :: fit_data_free
     129              : !!***
     130              : 
     131              : CONTAINS  !===========================================================================================
     132              : 
     133              : !!****f* m_fit_data/fit_data_init
     134              : !!
     135              : !! NAME
     136              : !! fit_data_init
     137              : !!
     138              : !! FUNCTION
     139              : !! Initialize fit_data datatype
     140              : !!
     141              : !! INPUTS
     142              : !! energy_diff(3,natom,ntime) = Difference of energy between DFT calculation and
     143              : !!                             fixed part of the model (more often harmonic part)
     144              : !! fcart_diff(3,natom,ntime) = Difference of cartesian forces between DFT calculation and
     145              : !!                             fixed part of the model (more often harmonic part)
     146              : !! natom = Number of atoms
     147              : !! ntime = Number of time (number of snapshot, number of md step...)
     148              : !! strten_diff(6,natom) = Difference of stress tensor between DFT calculation and
     149              : !!                        fixed part of the model (more often harmonic part)
     150              : !! sqomega(ntime) =  Sheppard and al Factors \Omega^{2} see J.Chem Phys 136, 074103 (2012) [[cite:Sheppard2012]]
     151              : !! ucvol(ntime) = Volume of the system for each time
     152              : !! ts<training_set_type> = datatype with the information about the training set
     153              : !!
     154              : !! OUTPUT
     155              : !! fit_data<fit_data_type> = fit_data datatype to be initialized
     156              : !!
     157              : !! SOURCE
     158              : 
     159           42 : subroutine fit_data_init(fit_data,energy_diff,fcart_diff,natom,ntime,strten_diff,ts)
     160              : 
     161              : !Arguments ------------------------------------
     162              : !scalars
     163              :  integer,intent(in) :: natom,ntime
     164              : !arrays
     165              :  real(dp),intent(in) :: energy_diff(ntime),fcart_diff(3,natom,ntime)
     166              :  real(dp),intent(in) :: strten_diff(6,ntime)
     167              :  type(training_set_type),intent(in) :: ts
     168              :  type(fit_data_type),intent(inout) :: fit_data
     169              : !Local variables-------------------------------
     170              : !scalar
     171              : !arrays
     172              :  character(len=500) :: message
     173              : ! *************************************************************************
     174              : 
     175           42 :  if(natom /= ts%natom)then
     176              :    write(message, '(a)')&
     177            0 : &      ' The number of atoms does not correspond to the training set'
     178            0 :    ABI_BUG(message)
     179              :  end if
     180              : 
     181           42 :  if(ntime /= ts%ntime)then
     182              :    write(message, '(a)')&
     183            0 : &      ' The number of time does not correspond to the training set'
     184            0 :    ABI_BUG(message)
     185              :  end if
     186              : 
     187              : !Free the output
     188           42 :  call fit_data_free(fit_data)
     189              : 
     190              : !Set integer values
     191           42 :  fit_data%ntime = ntime
     192           42 :  fit_data%natom = natom
     193              : 
     194              : !allocate arrays
     195          168 :  ABI_MALLOC(fit_data%fcart_diff,(3,natom,ntime))
     196       154763 :  fit_data%fcart_diff(:,:,:) = fcart_diff(:,:,:)
     197              : 
     198          126 :  ABI_MALLOC(fit_data%strten_diff,(6,ntime))
     199         6769 :  fit_data%strten_diff(:,:) = strten_diff(:,:)
     200              : 
     201          126 :  ABI_MALLOC(fit_data%energy_diff,(ntime))
     202         1003 :  fit_data%energy_diff(:) = energy_diff
     203              : 
     204              :  call training_set_init(fit_data%training_set,ts%displacement,ts%du_delta,&
     205           42 : &                       natom,ntime,ts%strain,ts%sqomega,ts%ucvol)
     206              : 
     207           42 : end subroutine fit_data_init
     208              : !!***
     209              : 
     210              : !!****f* m_fit_data/fit_data_free
     211              : !!
     212              : !! NAME
     213              : !! fit_data_free
     214              : !!
     215              : !! FUNCTION
     216              : !! Free the fit_data datatype
     217              : !!
     218              : !! INPUTS
     219              : !! fit_data<fit_data_type> = fit_data to be free
     220              : !! OUTPUT
     221              : !!
     222              : !! SOURCE
     223              : 
     224           82 : subroutine fit_data_free(fit_data)
     225              : 
     226              : !Arguments ------------------------------------
     227              : !scalars
     228              : !arrays
     229              :  type(fit_data_type),intent(inout) :: fit_data
     230              : !Local variables-------------------------------
     231              : !scalar
     232              : !arrays
     233              : ! *************************************************************************
     234              : 
     235              : ! Reset integer values
     236           82 :   fit_data%ntime = 0
     237           82 :   fit_data%natom = 0
     238              : 
     239              : ! Deallocate arrays
     240           82 :   if(allocated(fit_data%energy_diff)) then
     241           42 :     ABI_FREE(fit_data%energy_diff)
     242              :   end if
     243           82 :   if(allocated(fit_data%fcart_diff)) then
     244           42 :     ABI_FREE(fit_data%fcart_diff)
     245              :   end if
     246           82 :   if(allocated(fit_data%strten_diff)) then
     247           42 :     ABI_FREE(fit_data%strten_diff)
     248              :   end if
     249           82 :   call training_set_free(fit_data%training_set)
     250              : 
     251           82 : end subroutine fit_data_free
     252              : !!***
     253              : 
     254              : !!****f* m_fit_data/fit_data_compute
     255              : !!
     256              : !! NAME
     257              : !! fit_data_compute
     258              : !!
     259              : !! FUNCTION
     260              : !! Conpute the strain of each configuration.
     261              : !! Compute the displacmeent of each configuration.
     262              : !! Compute the variation of the displacement due to strain of each configuration.
     263              : !! Compute fixed forces and stresse and get the standard deviation.
     264              : !! Compute Sheppard and al Factors  \Omega^{2} see J.Chem Phys 136, 074103 (2012) [[cite:Sheppard2012]]
     265              : !!
     266              : !! INPUTS
     267              : !! eff_pot<type(effective_potential)> = effective potential
     268              : !! hist<type(abihist)> = The history of the MD (or snapshot of DFT
     269              : !! comm = MPI communicator
     270              : !! verbose  = optional, flag for the verbose mode
     271              : !!
     272              : !! OUTPUT
     273              : !! fit_data<fit_data_type> = fit_data is now filled
     274              : !!
     275              : !! SOURCE
     276              : 
     277           42 : subroutine fit_data_compute(fit_data,eff_pot,hist,comm,verbose)
     278              : 
     279              :  use m_strain,only : strain_type,strain_get
     280              :  use m_effective_potential,only : effective_potential_type,effective_potential_evaluate
     281              :  use m_effective_potential,only : effective_potential_getDisp
     282              :  use m_abihist, only : abihist
     283              :  use m_strain,only : strain_type,strain_get
     284              : 
     285              : !Arguments ------------------------------------
     286              : !scalars
     287              :  integer,intent(in) :: comm
     288              :  logical,optional,intent(in) :: verbose
     289              :  !arrays
     290              :  type(fit_data_type),intent(inout) :: fit_data
     291              :  type(effective_potential_type),intent(in) :: eff_pot
     292              :  type(abihist),intent(in) :: hist
     293              : !Local variables-------------------------------
     294              : !scalar
     295              :  integer :: ii,itime,natom,ntime
     296              :  real(dp):: energy
     297              :  logical :: need_verbose
     298              : !arrays
     299              :  character(len=500) :: message
     300              :  real(dp) :: gmet(3,3),gprimd(3,3),rmet(3,3)
     301           42 :  real(dp),allocatable :: energy_diff(:)
     302           42 :  real(dp),allocatable :: du_delta(:,:,:,:),displacement(:,:,:),strain(:,:)
     303           42 :  real(dp),allocatable :: fcart_diff(:,:,:),gred_fixed(:,:,:),fcart_fixed(:,:,:)
     304           42 :  real(dp),allocatable :: strten_diff(:,:),strten_fixed(:,:),sqomega(:),ucvol(:)
     305              :  type(strain_type) :: strain_t
     306           42 :  type(training_set_type) :: ts
     307              : ! *************************************************************************
     308              : 
     309              : !Initialisation of optional arguments
     310           42 :  need_verbose = .TRUE.
     311              :  if(present(verbose)) need_verbose = verbose
     312              : 
     313              : !Checks
     314           42 :  natom = eff_pot%supercell%natom
     315           42 :  ntime = hist%mxhist
     316           42 :  if(natom /= size(hist%xred,2))then
     317              :    write(message, '(5a)' )&
     318            0 : &      'The number of atoms in the hist file does not correspond to the supercell.',ch10,&
     319            0 : &      'You should call the routine fit_polynomial_coeff_mapHistToRef before',ch10,&
     320            0 : &      'Action: Contact abinit group'
     321            0 :    ABI_BUG(message)
     322              :  end if
     323              : 
     324              : !Allocation of temporary arrays
     325          168 :  ABI_MALLOC(displacement,(3,natom,ntime))
     326          168 :  ABI_MALLOC(du_delta,(6,3,natom,ntime))
     327          126 :  ABI_MALLOC(energy_diff,(ntime))
     328          126 :  ABI_MALLOC(fcart_fixed,(3,natom,ntime))
     329          126 :  ABI_MALLOC(fcart_diff,(3,natom,ntime))
     330          126 :  ABI_MALLOC(gred_fixed,(3,natom,ntime))
     331          126 :  ABI_MALLOC(strain,(6,ntime))
     332           84 :  ABI_MALLOC(strten_fixed,(6,ntime))
     333           84 :  ABI_MALLOC(strten_diff,(6,ntime))
     334           84 :  ABI_MALLOC(sqomega,(ntime))
     335           84 :  ABI_MALLOC(ucvol,(ntime))
     336              : 
     337       154763 :  displacement = zero
     338       846683 :  du_delta = zero
     339         6769 :  strain = zero;
     340       154763 :  fcart_fixed  = zero
     341       154763 :  gred_fixed  = zero
     342         6769 :  strain = zero
     343         6769 :  strten_fixed = zero
     344         6769 :  strten_diff = zero
     345         1003 :  sqomega = zero
     346         1003 :  ucvol = zero
     347              : 
     348         1003 :  do itime=1,ntime
     349              : !  Get strain
     350              :    call strain_get(strain_t,rprim=eff_pot%supercell%rprimd,&
     351          961 : &                  rprim_def=hist%rprimd(:,:,itime),symmetrized=.FALSE.)
     352          961 :    if (strain_t%name /= "reference")  then
     353         3844 :      do ii=1,3
     354         3844 :        strain(ii,itime) = strain_t%strain(ii,ii)
     355              :      end do
     356          961 :      strain(4,itime) = (strain_t%strain(2,3) + strain_t%strain(3,2))
     357          961 :      strain(5,itime) = (strain_t%strain(3,1) + strain_t%strain(1,3))
     358          961 :      strain(6,itime) = (strain_t%strain(2,1) + strain_t%strain(1,2))
     359              :    else
     360            0 :      strain(:,itime) = zero
     361              :    end if
     362              : 
     363              : !  Get displacement and du_delta
     364              :    call effective_potential_getDisp(displacement(:,:,itime),du_delta(:,:,:,itime),natom,&
     365              : &                                   hist%rprimd(:,:,itime),eff_pot%supercell%rprimd,comm,&
     366              : &                                   xred_hist=hist%xred(:,:,itime),xcart_ref=eff_pot%supercell%xcart,&
     367          961 : &                                   compute_displacement=.TRUE.,compute_duDelta=.TRUE.)
     368              : 
     369              : !  Get forces and stresses from harmonic part (fixed part)
     370              :    call effective_potential_evaluate(eff_pot,energy,fcart_fixed(:,:,itime),gred_fixed(:,:,itime),&
     371              : &                                    strten_fixed(:,itime),natom,hist%rprimd(:,:,itime),&
     372              : &                                    displacement=displacement(:,:,itime),&
     373              : &                                    du_delta=du_delta(:,:,:,itime),strain=strain(:,itime),&
     374          961 : &                                    compute_anharmonic=.true.,verbose=.FALSE.)
     375              : 
     376              : !  Compute \Omega^{2} and ucvol for each time
     377          961 :    call metric(gmet,gprimd,-1,rmet,hist%rprimd(:,:,itime),ucvol(itime))
     378              : !  Formula: sqomega(itime) = (((ucvol(itime)**(-2.))* ((natom)**(0.5)))**(-1.0/3.0))**2
     379              : !   Compact form:
     380          961 :    sqomega(itime) = ((ucvol(itime)**(4.0/3.0)) / ((natom)**(1/3.0)))
     381              : 
     382              : !  Compute the difference between History and model (fixed part)
     383       154721 :    fcart_diff(:,:,itime) =  hist%fcart(:,:,itime) - fcart_fixed(:,:,itime)
     384          961 :    energy_diff(itime)    =  hist%etot(itime) - energy
     385         6769 :    strten_diff(:,itime)  =  hist%strten(:,itime) - strten_fixed(:,itime)
     386              :  end do ! End Loop itime
     387              : 
     388              : !Set the training set
     389           42 :  call training_set_init(ts,displacement,du_delta,natom,ntime,strain,sqomega,ucvol)
     390              : !Set the fit_data
     391           42 :  call fit_data_init(fit_data,energy_diff,fcart_diff,natom,ntime,strten_diff,ts)
     392              : 
     393              : !Free space
     394           42 :  call training_set_free(ts)
     395           42 :  ABI_FREE(displacement)
     396           42 :  ABI_FREE(du_delta)
     397           42 :  ABI_FREE(energy_diff)
     398           42 :  ABI_FREE(fcart_fixed)
     399           42 :  ABI_FREE(fcart_diff)
     400           42 :  ABI_FREE(gred_fixed)
     401           42 :  ABI_FREE(strain)
     402           42 :  ABI_FREE(strten_fixed)
     403           42 :  ABI_FREE(strten_diff)
     404           42 :  ABI_FREE(sqomega)
     405           42 :  ABI_FREE(ucvol)
     406              : 
     407           42 : end subroutine fit_data_compute
     408              : !!***
     409              : 
     410              : 
     411              : 
     412              : 
     413              : !!****f* m_fit_data/training_set_init
     414              : !!
     415              : !! NAME
     416              : !! training_set_init
     417              : !!
     418              : !! FUNCTION
     419              : !! Initialize training_set datatype
     420              : !!
     421              : !! INPUTS
     422              : !! du_delta(6,3,natom,ntime)  = Variation to displacements wrt to the strain (Bohr)
     423              : !! displacement(3,natom,ntime)= Atomic displacement wrt to the reference (Bohr)
     424              : !! natom = number of atoms
     425              : !! ntime = number of time step
     426              : !! strain(6,ntime) = Strain
     427              : !! sqomega =  Sheppard and al Factors \Omega^{2} see J.Chem Phys 136, 074103 (2012) [[cite:Sheppard2012]]
     428              : !! ucvol(ntime) = Volume of the supercell for each time (Bohr^3)
     429              : !!
     430              : !! OUTPUT
     431              : !! ts<training_set_type> = training set to be initialized
     432              : !!
     433              : !! SOURCE
     434              : 
     435           84 : subroutine training_set_init(ts,displacement,du_delta,natom,ntime,strain,sqomega,ucvol)
     436              : 
     437              : !Arguments ------------------------------------
     438              : !scalars
     439              :  integer,intent(in) :: natom,ntime
     440              : !arrays
     441              :  real(dp),intent(in) :: displacement(3,natom,ntime),du_delta(6,3,natom,ntime)
     442              :  real(dp),intent(in) :: strain(6,ntime),sqomega(ntime),ucvol(ntime)
     443              :  type(training_set_type),intent(inout) :: ts
     444              : !Local variables-------------------------------
     445              : !scalar
     446              : !arrays
     447              : ! *************************************************************************
     448              : 
     449              : !Free the output
     450           84 :  call training_set_free(ts)
     451              : 
     452              : !Set integer values
     453           84 :  ts%ntime = ntime
     454           84 :  ts%natom = natom
     455              : 
     456              : !allocate arrays
     457          336 :  ABI_MALLOC(ts%displacement,(3,natom,ntime))
     458       309526 :  ts%displacement(:,:,:) = displacement(:,:,:)
     459              : 
     460          336 :  ABI_MALLOC(ts%du_delta,(6,3,natom,ntime))
     461      1693366 :  ts%du_delta(:,:,:,:) = du_delta(:,:,:,:)
     462              : 
     463          252 :  ABI_MALLOC(ts%strain,(6,ntime))
     464        13538 :  ts%strain(:,:) = strain(:,:)
     465              : 
     466          252 :  ABI_MALLOC(ts%sqomega,(ntime))
     467         2006 :  ts%sqomega(:) = sqomega(:)
     468              : 
     469          168 :  ABI_MALLOC(ts%ucvol,(ntime))
     470         2006 :  ts%ucvol(:) = ucvol(:)
     471              : 
     472           42 : end subroutine training_set_init
     473              : !!***
     474              : 
     475              : !!****f* m_fit_data/training_set_free
     476              : !!
     477              : !! NAME
     478              : !! training_set_free
     479              : !!
     480              : !! FUNCTION
     481              : !! Free the training_set datatype
     482              : !!
     483              : !! INPUTS
     484              : !! training_set<training_set_type> = training_set to be free
     485              : !! OUTPUT
     486              : !!
     487              : !! SOURCE
     488              : 
     489          208 : subroutine training_set_free(ts)
     490              : 
     491              : !Arguments ------------------------------------
     492              : !scalars
     493              : !arrays
     494              :  type(training_set_type),intent(inout) :: ts
     495              : !Local variables-------------------------------
     496              : !scalar
     497              : !arrays
     498              : ! *************************************************************************
     499              : 
     500              : ! Reset integer values
     501          208 :   ts%ntime = 0
     502          208 :   ts%natom = 0
     503              : 
     504              : ! Deallocate arrays
     505          208 :   if(allocated(ts%displacement)) then
     506           84 :     ABI_FREE(ts%displacement)
     507              :   end if
     508          208 :   if(allocated(ts%du_delta)) then
     509           84 :     ABI_FREE(ts%du_delta)
     510              :   end if
     511          208 :   if(allocated(ts%strain)) then
     512           84 :     ABI_FREE(ts%strain)
     513              :   end if
     514          208 :   if(allocated(ts%sqomega))then
     515           84 :     ABI_FREE(ts%sqomega)
     516              :   end if
     517          208 :   if(allocated(ts%ucvol)) then
     518           84 :     ABI_FREE(ts%ucvol)
     519              :   end if
     520              : 
     521          208 : end subroutine training_set_free
     522              : !!***
     523              : 
     524            0 : end module m_fit_data
     525              : !!***
        

Generated by: LCOV version 2.3-1