~albertog/siesta/efield-2.5-jjunquera

« back to all changes in this revision

Viewing changes to Src/zm_broyden_optim.F

  • Committer: Alberto Garcia
  • Date: 2007-06-04 15:47:56 UTC
  • mfrom: (unknown (missing))
  • Revision ID: Arch-1:siesta@uam.es--2006%siesta-devel--reference--2.1--patch-61
Zmatrix optimization enhancements. Sign change in MM stress.
* Added constant-volume optimization option to the Zmatrix code.

* Broyden option for Zmatrix optimization.

* The zmatrix optimization code for the "variable cell" case has been
partially fixed. It now fails to work only if some of the coordinates
of an atom specifed in "cartesian" form are variables (i.e., allowed
to relax) and others are not.

For example:

cartesian  
...
     1  0.3 0.4 0.5    1 0 1
...

will fail as the second coordinate is not allowed to relax.

     1 0.4 0.2 -0.7    0 0 0         OK
     1 0.4 0.2 -0.7    1 1 1         OK


* New file cell_broyden_optim.F implements "cell-only" optimizations.

This feature is enabled by setting the symbol

MD.RelaxCellOnly 

to .true..

Only the cell parameters are relaxed (by the Broyden method).  The
atomic coordinates are re-scaled to the new cell, keeping the
fractional coordinates constant. For Zmatrix calculations, the
fractional position of the first atom in each molecule is kept fixed,
and no attempt is made to rescale the bond distances or angles.

* Removal of intra-molecular pressure

If the symbol

MD.RemoveIntramolecularPressure

is set to .true., the contribution to the stress coming from the
internal degrees of freedom of the molecules will be subtracted.  This
is done in an approximate manner, using the virial form of the stress,
and assumming that the "mean force" over the coordinates of the
molecule represents the "inter-molecular" stress. The correction term
was already computed in earlier versions ("Pmol"). The correction is
now computed molecule-by-molecule if the Zmatrix format is used.

NOTE: The reported "Molecular Pressure" might change slightly from
previous versions as the "current" and not the "next iteration" coordinates
are used for the computation of the virial term.


If the intra-molecular stress is removed, the corrected static and
total stresses are printed in addition to the uncorrected items.

The corrected Voigt form is also printed.

(New test ch4 to exemplify this feature)


* Correction of the sign of the stress in molecularmechanics.F90

For MM potentials, attractive interactions are represented by
*positive* C coefficients in the MM.Potentials block. Then the
MM energy is negative, as it should be. However, the sign of
the stress was wrong in the original implementation. Now (also
printed as MM-Stress) it should come out as a positive contribution
(negative pressure), forcing the cell to contract.

(Updated graphite_full test)


* New Utils/MM_Examples directory.

An example of the use of MM potentials to introduce van der Waals
interactions in an approximate manner (for the artificial example
of fcc He).

* Additional enthalpy-analog output.

The enthalpy is computed in two ways: as the "target enthalpy" using
the target pressure, and as the "real" enthalpy using the trace of the
current stress tensor as an estimation of the pressure. Ideally, both
values should be identical at convergence, but the "target enthalpy"
might have significant errors coming from the tolerances.


* NEW STRUCTURE OUTPUT FILES:

OUT.UCELL.ZMATRIX

It contains the structural information in fdf form, with
blocks for unit-cell vectors and for Zmatrix coordinates. The
Zmatrix block is in a ``canonical'' form with the following
characteristics:

1. No symbolic variables or constants are used.
2. The position coordinates of the first atom in each molecule
   are absolute cartesian coordinates.
3. Any coordinates in ``cartesian'' blocks are also absolute cartesians.
4. There is no provision for output of constraints.
5. The units used are those initially specified by the user, and are
   noted also in fdf form.

Note that the geometry reported is the last one for which forces and
stresses were computed.

NEXT_ITER.UCELL.ZMATRIX

In the same format but with a possibly updated geometry.

Label.STRUCT_NEXT_ITER.

Structure in crystallographic format (same as Label.STRUCT_OUT) for a
possibly updated geometry.

(Call performed in siesta_write_positions, which is called after the
structure has moved after the application of forces/stress.)


* New .make file for Hreidar at ETH Zurich.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
2
! This file is part of the SIESTA package.
 
3
!
 
4
! Copyright (c) Fundacion General Universidad Autonoma de Madrid:
 
5
! E.Artacho, J.Gale, A.Garcia, J.Junquera, P.Ordejon, D.Sanchez-Portal
 
6
! and J.M.Soler, 1996-2006.
 
7
 
8
! Use of this software constitutes agreement with the full conditions
 
9
! given in the SIESTA license, as signed by all legitimate users.
 
10
!
 
11
      module m_zm_broyden_optim
 
12
      public :: zm_broyden_optimizer
 
13
      private
 
14
 
 
15
      CONTAINS
 
16
!
 
17
      subroutine zm_broyden_optimizer( na, xa, fa, cell,
 
18
     .                 stress, volume, dxmax, 
 
19
     .                 tp, ftol, strtol, varcel, relaxd)
 
20
 
 
21
c ******************************** INPUT ************************************
 
22
c integer na            : Number of atoms in the simulation cell
 
23
c real*8 fa(3,na)       : Atomic forces
 
24
c real*8 stress(3,3)    : Stress tensor components
 
25
c real*8 volume         : unit cell volume
 
26
c real*8 dxmax          : Maximum atomic (or lattice vector) displacement
 
27
c real*8 tp             : Target pressure
 
28
c real*8 ftol           : Maximum force tolerance
 
29
c real*8 strtol         : Maximum stress tolerance
 
30
c logical varcel        : true if variable cell optimization
 
31
c *************************** INPUT AND OUTPUT ******************************
 
32
c real*8 xa(3,na)       : Atomic coordinates
 
33
c                         input: current step; output: next step
 
34
c real*8 cell(3,3)      : Matrix of the vectors defining the unit cell 
 
35
c                         input: current step; output: next step
 
36
c                         cell(ix,ja) is the ix-th component of ja-th vector
 
37
c real*8 stress(3,3)    : Stress tensor components
 
38
c real*8 strtol         : Maximum stress tolerance
 
39
c ******************************** OUTPUT ***********************************
 
40
c logical relaxd        : True when converged
 
41
c ***************************************************************************
 
42
 
 
43
C
 
44
C  Modules
 
45
C
 
46
      use precision,   only : dp
 
47
      use parallel,    only : Node, IONode
 
48
      use fdf,         only : fdf_block, fdf_physical
 
49
      use m_fdf_global, only: fdf_global_get
 
50
      use m_mpi_utils, only:  broadcast
 
51
      use units, only: kBar, Ang
 
52
      use m_broyddj_nocomm, only: broyden_t
 
53
      use m_broyddj_nocomm, only: broyden_reset, broyden_step,
 
54
     $                     broyden_destroy, broyden_init,
 
55
     $                     broyden_is_setup
 
56
 
 
57
      use zmatrix,     only : VaryZmat, Zmat
 
58
      use zmatrix,     only : CartesianForce_to_ZmatForce
 
59
      use zmatrix,     only : ZmatForce,ZmatForceVar
 
60
      use zmatrix,     only : iZmattoVars,ZmatType
 
61
      use zmatrix,     only : Zmat_to_Cartesian
 
62
      use zmatrix,     only : coeffA, coeffB, iNextDept
 
63
      use Zmatrix,     only : ZmatForceTolLen, ZmatForceTolAng
 
64
      use Zmatrix,     only : ZmatMaxDisplLen, ZmatMaxDisplAng
 
65
 
 
66
      implicit none
 
67
 
 
68
C Subroutine arguments:
 
69
      integer,  intent(in)   :: na
 
70
      logical,  intent(in)   :: varcel
 
71
      logical,  intent(out)  :: relaxd
 
72
      real(dp), intent(in)   :: fa(3,na), volume, dxmax, tp, ftol
 
73
      real(dp), intent(inout):: xa(3,na), stress(3,3), strtol, cell(3,3)
 
74
 
 
75
C Internal variables and arrays
 
76
      integer             :: iu, ia, i, j, n, indi,indi1,vi,k
 
77
      logical             :: found
 
78
      real(dp)            :: new_volume, trace
 
79
      real(dp)            :: sxx, syy, szz, sxy, sxz, syz
 
80
      real(dp)            :: celli(3,3)
 
81
      real(dp)            ::  stress_dif(3,3)
 
82
      real(dp), dimension(:), allocatable :: gxa, gfa
 
83
      real(dp)            :: force, force1
 
84
 
 
85
C Saved internal variables:
 
86
      integer,       save :: ndeg
 
87
      logical,       save :: frstme = .true.
 
88
      logical,       save :: tarstr = .false.
 
89
      logical,       save :: constant_volume
 
90
      real(dp),      save :: initial_volume
 
91
 
 
92
      real(dp),      save :: tstres(3,3) 
 
93
      real(dp),      save :: cellin(3,3) 
 
94
      real(dp),      save :: modcel(3) 
 
95
      real(dp),      save :: precon 
 
96
      real(dp),      save :: strain(3,3)  ! Special treatment !!
 
97
 
 
98
      real(dp), dimension(:), allocatable    :: ftoln, dxmaxn
 
99
      real(dp), dimension(:), allocatable    :: rold, rnew, rdiff
 
100
 
 
101
      type(broyden_t), save  :: br
 
102
      logical, save           :: initialization_done = .false.
 
103
 
 
104
      real(dp), save :: jinv0
 
105
      integer, save  :: maxit
 
106
      logical, save  :: cycle_on_maxit, variable_weight
 
107
      logical, save  :: broyden_debug
 
108
      real(dp)       :: weight
 
109
 
 
110
      integer        :: ndegi, ndi
 
111
 
 
112
      external          memory
 
113
      real(dp), external :: volcel
 
114
 
 
115
c ---------------------------------------------------------------------------
 
116
 
 
117
      if (.not. initialization_done) then
 
118
 
 
119
          call fdf_global_get(maxit,"MD.Broyden.History.Steps",5)
 
120
          call fdf_global_get(cycle_on_maxit,
 
121
     $              "MD.Broyden.Cycle.On.Maxit",.true.)
 
122
          call fdf_global_get(variable_weight,
 
123
     $         "MD.Broyden.Variable.Weight",.false.)
 
124
          call fdf_global_get(broyden_debug,
 
125
     $         "MD.Broyden.Debug",.false.)
 
126
          call fdf_global_get(jinv0,
 
127
     $         "MD.Broyden.Initial.Inverse.Jacobian",1.0_dp)
 
128
 
 
129
         if (ionode) then
 
130
          write(6,*) 
 
131
          write(6,'(a,i3)')
 
132
     $         "Broyden_optim: max_history for broyden: ", maxit
 
133
          write(6,'(a,l1)')
 
134
     $         "Broyden_optim: cycle on maxit: ", cycle_on_maxit
 
135
          if (variable_weight) write(6,'(a)')
 
136
     $         "Broyden_optim: Variable weight not implemented yet"
 
137
          write(6,'(a,f8.4)')
 
138
     $         "Broyden_optim: initial inverse jacobian: ", jinv0
 
139
          write(6,*) 
 
140
        endif
 
141
 
 
142
         call broyden_init(br,debug=broyden_debug)
 
143
         initialization_done = .true.
 
144
 
 
145
      endif
 
146
 
 
147
      if ( frstme ) then
 
148
  
 
149
        ! Find number of variables
 
150
        ndeg = 0
 
151
        do ia = 1,na
 
152
           do n = 1,3
 
153
              indi = 3*(ia-1) + n
 
154
              if (VaryZmat(indi)) then
 
155
                 ndeg = ndeg + 1
 
156
              endif
 
157
           enddo
 
158
        enddo
 
159
        if ( varcel ) then
 
160
           ndeg = ndeg + 6      ! Including stress
 
161
        endif
 
162
        if (Ionode) then
 
163
           write(6,'(a,i6)') "Broyden_optim: No of elements: ", ndeg
 
164
        endif
 
165
 
 
166
        if ( varcel ) then
 
167
 
 
168
          call fdf_global_get(constant_volume,
 
169
     .                        "MD.ConstantVolume", .false.)
 
170
 
 
171
          if (Node.eq.0) then
 
172
            tarstr = fdf_block('MD.TargetStress',iu)
 
173
 
 
174
            ! Look for target stress and read it if found, 
 
175
            ! otherwise generate it
 
176
            if (tarstr) then
 
177
              write(6,'(/a,a)')
 
178
     $              'cgvc_zmatrix: Reading %block MD.TargetStress',
 
179
     .                       ' (units of MD.TargetPressure).'
 
180
              read(iu,*, end=50) sxx, syy, szz, sxy, sxz, syz
 
181
              tstres(1,1) = - sxx * tp
 
182
              tstres(2,2) = - syy * tp
 
183
              tstres(3,3) = - szz * tp
 
184
              tstres(1,2) = - sxy * tp
 
185
              tstres(2,1) = - sxy * tp
 
186
              tstres(1,3) = - sxz * tp
 
187
              tstres(3,1) = - sxz * tp
 
188
              tstres(2,3) = - syz * tp
 
189
              tstres(3,2) = - syz * tp
 
190
   50         continue
 
191
            else
 
192
              write(6,'(/a,a)')
 
193
     $              'cgvc_zmatrix: No target stress found, ',
 
194
     .              'assuming hydrostatic MD.TargetPressure.'
 
195
              do i = 1, 3
 
196
                do j = 1, 3
 
197
                  tstres(i,j) = 0.0_dp
 
198
                enddo
 
199
                tstres(i,i) = - tp
 
200
              enddo
 
201
            endif
 
202
 
 
203
            if (constant_volume) then
 
204
               tstres(:,:) = 0.0_dp
 
205
               write(6,"(a)") "***Target stress set to zero " //
 
206
     $              "for constant-volume calculation"
 
207
            endif
 
208
            write(6,"(/a)") 'cgvc_zmatrix: Target stress (kBar)'
 
209
            do i=1, 3
 
210
               write(6,"(a,2x,3f12.3)") 
 
211
     .              'cgvc_zmatrix:', (tstres(i,j)/kBar,j=1,3)
 
212
            enddo
 
213
          endif
 
214
 
 
215
          call broadcast(tstres(1:3,1:3))
 
216
 
 
217
C Moduli of original cell vectors for fractional coor scaling back to au ---
 
218
          do n = 1, 3
 
219
            modcel(n) = 0.0_dp
 
220
            do j = 1, 3
 
221
              modcel(n) = modcel(n) + cell(j,n)*cell(j,n)
 
222
            enddo
 
223
            modcel(n) = dsqrt( modcel(n) )
 
224
          enddo
 
225
 
 
226
C Scale factor for strain variables to share magnitude with coordinates
 
227
C ---- (a length in Bohrs typical of bond lengths ..) 
 
228
 
 
229
          ! AG: This could better be volume^(1/3) by default
 
230
          call fdf_global_get(precon,'MD.PreconditionVariableCell',
 
231
     .                           9.4486344d0,'Bohr')
 
232
 
 
233
C Initialize absolute strain and save initial cell vectors
 
234
C Initialization to 1 for numerical reasons, later substracted
 
235
       
 
236
          strain(1:3,1:3) = 1.0_dp
 
237
          cellin(1:3,1:3) = cell(1:3,1:3)
 
238
          initial_volume = volcel(cellin)
 
239
 
 
240
        endif     ! varcel
 
241
 
 
242
 
 
243
        frstme = .false.
 
244
      endif                 ! First time
 
245
 
 
246
C Allocate local memory
 
247
 
 
248
      allocate(gfa(ndeg))
 
249
      call memory('A','D',ndeg,'cgvc_zmatrix')
 
250
      allocate(gxa(ndeg))
 
251
      call memory('A','D',ndeg,'cgvc_zmatrix')
 
252
      allocate(ftoln(ndeg))
 
253
      call memory('A','D',ndeg,'cgvc_zmatrix')
 
254
      allocate(dxmaxn(ndeg))
 
255
      call memory('A','D',ndeg,'cgvc_zmatrix')
 
256
 
 
257
!      print *, "zm_broyden: cell in : ", cell
 
258
!      print *, "zm_broyden: strain in : ", strain
 
259
 
 
260
      if ( varcel ) then
 
261
 
 
262
        ! Inverse of matrix of cell vectors  (transpose of)
 
263
        call reclat( cell, celli, 0 )
 
264
 
 
265
C Transform coordinates and forces to fractional ---------------------------- 
 
266
C but scale them again to Bohr by using the (fix) moduli of the original ----
 
267
C lattice vectors (allows using maximum displacement as before) -------------
 
268
C convergence is checked here for input forces as compared with ftol --------
 
269
 
 
270
        relaxd = .true.
 
271
        ndegi = 0
 
272
        ! Loop over degrees of freedom, scaling 
 
273
        ! only cartesian coordinates to fractional
 
274
          do ia = 1,na
 
275
            do n = 1,3
 
276
              indi = 3*(ia-1) + n
 
277
              if (VaryZmat(indi)) then
 
278
                ndegi = ndegi + 1
 
279
                if (ZmatType(indi).gt.1) then
 
280
                  ftoln(ndegi) = ZmatForceTolLen
 
281
                  dxmaxn(ndegi) = ZmatMaxDisplLen
 
282
                else
 
283
                  ftoln(ndegi) = ZmatForceTolAng
 
284
                  dxmaxn(ndegi) = ZmatMaxDisplAng
 
285
                endif
 
286
                vi = iZmattoVars(indi)
 
287
                if (vi.eq.0) then
 
288
                  force = ZmatForce(indi)
 
289
                else
 
290
                  force = ZmatForceVar(vi)
 
291
                endif 
 
292
                relaxd=relaxd.and.(dabs(force).lt.ftoln(ndegi))
 
293
                if (ZmatType(indi).gt.2) then
 
294
C Cartesian coordinate                
 
295
                  gxa(ndegi) = 0.0_dp
 
296
                  gfa(ndegi) = 0.0_dp
 
297
                  do i = 1,3
 
298
                    indi1 = 3*(ia-1)+i
 
299
                    gxa(ndegi) = gxa(ndegi)+
 
300
     .                          celli(i,n)*Zmat(indi1)*modcel(n)
 
301
                    if (i.eq.n) then
 
302
                      force1 = force
 
303
                    else
 
304
                      force1 = ZmatForce(indi1)
 
305
                    endif
 
306
                    gfa(ndegi) = gfa(ndegi)+ 
 
307
     .                          cell(i,n)*force1/modcel(n)
 
308
                  enddo
 
309
                else
 
310
                  gxa(ndegi) = Zmat(indi)
 
311
                  gfa(ndegi) = force
 
312
                endif
 
313
              endif
 
314
            enddo
 
315
          enddo
 
316
 
 
317
C Symmetrizing the stress tensor --------------------------------------------
 
318
        do i = 1,3
 
319
          do j = i+1,3
 
320
            stress(i,j) = 0.5_dp*( stress(i,j) + stress(j,i) )
 
321
            stress(j,i) = stress(i,j)
 
322
          enddo
 
323
        enddo
 
324
 
 
325
C Subtract target stress
 
326
 
 
327
        stress_dif = stress - tstres
 
328
!
 
329
!       Take 1/3 of the trace out here if constant-volume needed
 
330
!
 
331
        if (constant_volume) then
 
332
           trace = stress_dif(1,1) + stress_dif(2,2) + stress_dif(3,3)
 
333
           do i=1,3
 
334
              stress_dif(i,i) = stress_dif(i,i) - trace/3.0_dp
 
335
           enddo
 
336
        endif
 
337
 
 
338
C Append stress (substracting target stress) and strain to gxa and gfa ------ 
 
339
C preconditioning: scale stress and strain so as to behave similarly to x,f -
 
340
        do i = 1,3
 
341
          do j = i,3
 
342
            ndegi = ndegi + 1
 
343
            gfa(ndegi) = -stress_dif(i,j)*volume/precon
 
344
            gxa(ndegi) = strain(i,j) * precon
 
345
            dxmaxn(ndegi) = ZmatMaxDisplLen
 
346
          enddo
 
347
        enddo
 
348
 
 
349
C Check stress convergence
 
350
        strtol = dabs(strtol)
 
351
        do i = 1,3
 
352
          do j = 1,3
 
353
            relaxd = relaxd .and. 
 
354
     .        ( dabs(stress_dif(i,j)) .lt. abs(strtol) )
 
355
          enddo
 
356
        enddo
 
357
 
 
358
      else   ! FIXED CELL
 
359
 
 
360
C Set number of degrees of freedom & variables
 
361
         relaxd = .true.
 
362
        ndegi = 0
 
363
          do i = 1,na
 
364
            do k = 1,3
 
365
              indi = 3*(i-1)+k
 
366
              if (VaryZmat(indi)) then
 
367
                ndegi = ndegi + 1
 
368
                gxa(ndegi) = Zmat(indi)
 
369
                vi = iZmattoVars(indi)
 
370
                if (vi.eq.0) then
 
371
                  force = ZmatForce(indi)
 
372
                else
 
373
                  force = ZmatForceVar(vi)
 
374
                endif
 
375
                gfa(ndegi) = force
 
376
                if (ZmatType(indi).eq.1) then
 
377
                  ftoln(ndegi) = ZmatForceTolAng
 
378
                  dxmaxn(ndegi) = ZmatMaxDisplAng
 
379
                else
 
380
                  ftoln(ndegi) = ZmatForceTolLen
 
381
                  dxmaxn(ndegi) = ZmatMaxDisplLen
 
382
                endif
 
383
                relaxd=relaxd.and.(dabs(force).lt.ftoln(ndegi))
 
384
              endif
 
385
            enddo
 
386
          enddo
 
387
 
 
388
      endif
 
389
 
 
390
      if (relaxd) RETURN   ! Will leave work arrays allocated
 
391
 
 
392
      if (.not. broyden_is_setup(br)) then
 
393
         call broyden_reset(br,ndeg,maxit,cycle_on_maxit,
 
394
     $        jinv0,0.01_dp)
 
395
      endif
 
396
      allocate (rnew(ndeg))
 
397
      call memory('A','D',ndeg,'zm_broyden_optimizer')
 
398
      weight = 1.0_dp
 
399
      call broyden_step(br,gxa,gfa,w=weight,newx=rnew)
 
400
 
 
401
 
 
402
      ! Transform back
 
403
      if ( varcel) then
 
404
 
 
405
        ! New cell
 
406
        indi = ndeg-6
 
407
        do i = 1,3
 
408
          do j = i,3
 
409
            indi = indi + 1
 
410
            strain(i,j) = rnew(indi) / precon
 
411
            strain(j,i) = strain(i,j)
 
412
          enddo
 
413
        enddo
 
414
 
 
415
        cell = cellin + matmul(strain-1.0_dp,cellin)
 
416
        if (constant_volume) then
 
417
           new_volume = volcel(cell)
 
418
           if (Node.eq.0) write(6,"(a,f12.4)")
 
419
     $          "Volume before coercion: ",  new_volume/Ang**3
 
420
           cell =  cell * (initial_volume/new_volume)**(1.0_dp/3.0_dp)
 
421
        endif
 
422
 
 
423
C Output fractional coordinates to cartesian Bohr, and copy to xa ----------- 
 
424
        ndegi = 0
 
425
        do ia=1,na
 
426
            do k=1,3
 
427
              indi = 3*(ia-1)+k
 
428
              if (VaryZmat(indi)) then
 
429
                ndegi = ndegi + 1
 
430
                j = indi
 
431
                do while (j.ne.0) 
 
432
                  if (ZmatType(j).gt.2) then
 
433
                    Zmat(j) = 0.0_dp
 
434
                    do n=1,3
 
435
                      indi1 = 3*(ia-1)+n
 
436
                      ! Assume all three coords of this atom
 
437
                      ! are variables
 
438
                      ndi = ndegi + n - k
 
439
                      Zmat(j)=Zmat(j)+cell(k,n)*rnew(ndi)/modcel(n)
 
440
                    enddo
 
441
                  else
 
442
                    Zmat(j) = rnew(ndegi)
 
443
                  endif
 
444
                  Zmat(j) = Zmat(j)*coeffA(j) + coeffB(j)
 
445
                  j = iNextDept(j)
 
446
                enddo
 
447
              endif
 
448
            enddo
 
449
          enddo  
 
450
          call Zmat_to_Cartesian(xa)
 
451
 
 
452
      else
 
453
C Fixed cell
 
454
C Return coordinates to correct arrays 
 
455
        ndegi = 0
 
456
          do ia = 1,na
 
457
            do k = 1,3
 
458
              indi = 3*(ia-1)+k
 
459
              if (VaryZmat(indi)) then
 
460
                ndegi = ndegi + 1
 
461
                j = indi
 
462
                do while (j.ne.0)
 
463
                  Zmat(j) = rnew(ndegi)*coeffA(j)+coeffB(j)
 
464
                  j = iNextDept(j)
 
465
                enddo
 
466
              endif
 
467
            enddo
 
468
          enddo
 
469
          call Zmat_to_Cartesian(xa)
 
470
      endif
 
471
 
 
472
!      print *, "zm_broyden: cell out : ", cell
 
473
!      print *, "zm_broyden: strain out : ", strain
 
474
 
 
475
C Deallocate local memory
 
476
 
 
477
      call memory('D','D',size(dxmaxn),'cgvc_zmatrix')
 
478
      deallocate(dxmaxn)
 
479
      call memory('D','D',size(ftoln),'cgvc_zmatrix')
 
480
      deallocate(ftoln)
 
481
      call memory('D','D',size(gxa),'cgvc_zmatrix')
 
482
      deallocate(gxa)
 
483
      call memory('D','D',size(gfa),'cgvc_zmatrix')
 
484
      deallocate(gfa)
 
485
      call memory('D','D',size(rnew),'cgvc_zmatrix')
 
486
      deallocate(rnew)
 
487
 
 
488
      end subroutine zm_broyden_optimizer
 
489
 
 
490
      end module m_zm_broyden_optim