diff --git a/CMakeLists.txt b/CMakeLists.txt index 000b25dde8..c6b7786366 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,7 +99,6 @@ LIST(APPEND PROCESS_SRCS structure_variables.f90 output.f90 init_module.f90 - main_module.f90 error_handling.f90 global_variables.f90 constraint_variables.f90 diff --git a/process/init.py b/process/init.py index 53bc345a90..b67ff58ddf 100644 --- a/process/init.py +++ b/process/init.py @@ -1,7 +1,14 @@ +import datetime +import getpass +import socket +import subprocess +from pathlib import Path from warnings import warn +import process import process.fortran as fortran from process.exceptions import ProcessValidationError +from process.utilities.f2py_string_patch import f2py_compatible_to_string def init_process(): @@ -31,7 +38,162 @@ def init_process(): # Check input data for errors/ambiguities check_process() - fortran.main_module.run_summary() + run_summary() + + +def get_git_summary() -> tuple[str, str]: + try: + directory = Path(process.__file__).parent + + git_branch = ( + subprocess.run( + "git rev-parse --abbrev-ref HEAD", + shell=True, + capture_output=True, + cwd=directory, + check=True, + ) + .stdout.decode() + .strip() + ) + + git_tag = ( + subprocess.run( + "git describe --tags", + shell=True, + capture_output=True, + cwd=directory, + check=True, + ) + .stdout.decode() + .strip() + ) + + return git_branch, git_tag + except (subprocess.CalledProcessError, AttributeError): + return "", "" + + +def run_summary(): + """Write a summary of the PROCESS run to the output file and MFile""" + # Outfile and terminal # + for outfile in [fortran.constants.nout, fortran.constants.iotty]: + # PROCESS code header + fortran.process_output.oblnkl(outfile) + fortran.process_output.ostars(outfile, 110) + fortran.process_output.ocentr(outfile, "PROCESS", 110) + fortran.process_output.ocentr(outfile, "Power Reactor Optimisation Code", 110) + fortran.process_output.ostars(outfile, 110) + fortran.process_output.oblnkl(outfile) + + # Run execution details + version = process.__version__ + fortran.process_output.ocmmnt(outfile, f"Version : {version}") + + git_branch, git_tag = get_git_summary() + + fortran.process_output.ocmmnt(outfile, f"Git Tag : {git_tag}") + fortran.process_output.ocmmnt(outfile, f"Git Branch : {git_branch}") + + date_string = datetime.datetime.now(datetime.timezone.utc).strftime( + "%d/%m/%Y %Z" + ) + time_string = datetime.datetime.now(datetime.timezone.utc).strftime("%H:%M") + + fortran.process_output.ocmmnt(outfile, f"Date : {date_string}") + fortran.process_output.ocmmnt(outfile, f"Time : {time_string}") + + user = getpass.getuser() + machine = socket.gethostname() + + fortran.process_output.ocmmnt(outfile, f"User : {user}") + fortran.process_output.ocmmnt(outfile, f"Computer : {machine}") + fortran.process_output.ocmmnt(outfile, f"Directory : {Path.cwd()}") + + fileprefix = f2py_compatible_to_string(fortran.global_variables.fileprefix) + fortran.process_output.ocmmnt( + outfile, + f"Input : {fileprefix}", + ) + runtitle = f2py_compatible_to_string(fortran.global_variables.runtitle) + fortran.process_output.ocmmnt( + outfile, + f"Run title : {runtitle}", + ) + + fortran.process_output.ocmmnt( + outfile, + f"Run type : Reactor concept design: {f2py_compatible_to_string(fortran.global_variables.icase)}, (c) UK Atomic Energy Authority", + ) + + fortran.process_output.oblnkl(outfile) + fortran.process_output.ostars(outfile, 110) + fortran.process_output.oblnkl(outfile) + + fortran.process_output.ocmmnt( + outfile, f"Equality constraints : {fortran.numerics.neqns.item()}" + ) + fortran.process_output.ocmmnt( + outfile, f"Inequality constraints : {fortran.numerics.nineqns.item()}" + ) + fortran.process_output.ocmmnt( + outfile, + f"Total constraints : {fortran.numerics.nineqns.item() + fortran.numerics.neqns.item()}", + ) + fortran.process_output.ocmmnt( + outfile, f"Iteration variables : {fortran.numerics.nvar.item()}" + ) + fortran.process_output.ocmmnt( + outfile, f"Max iterations : {fortran.global_variables.maxcal.item()}" + ) + + if fortran.numerics.minmax > 0: + minmax_string = " -- minimise " + minmax_sign = "+" + else: + minmax_string = " -- maximise " + minmax_sign = "-" + + fom_string = f2py_compatible_to_string( + fortran.numerics.lablmm[abs(fortran.numerics.minmax) - 1] + ) + fortran.process_output.ocmmnt( + outfile, + f"Figure of merit : {minmax_sign}{abs(fortran.numerics.minmax)}{minmax_string}{fom_string}", + ) + fortran.process_output.ocmmnt( + outfile, + f"Convergence parameter : {fortran.numerics.epsvmc}", + ) + + fortran.process_output.oblnkl(outfile) + fortran.process_output.ostars(outfile, 110) + + # MFile # + mfile = fortran.constants.mfile + + fortran.process_output.ovarst(mfile, "PROCESS version", "(procver)", f'"{version}"') + fortran.process_output.ovarst(mfile, "Date of run", "(date)", f'"{date_string}"') + fortran.process_output.ovarst(mfile, "Time of run", "(time)", f'"{time_string}"') + fortran.process_output.ovarst(mfile, "User", "(username)", f'"{user}"') + fortran.process_output.ovarst( + mfile, "PROCESS run title", "(runtitle)", f'"{runtitle}"' + ) + fortran.process_output.ovarst(mfile, "PROCESS git tag", "(tagno)", f'"{git_tag}"') + fortran.process_output.ovarst( + mfile, "PROCESS git branch", "(branch_name)", f'"{git_branch}"' + ) + fortran.process_output.ovarst( + mfile, "Input filename", "(fileprefix)", f'"{fileprefix}"' + ) + + fortran.process_output.ovarin( + mfile, "Optimisation switch", "(ioptimz)", fortran.numerics.ioptimz + ) + if fortran.numerics.ioptimz == -2: + fortran.process_output.ovarin( + mfile, "Figure of merit switch", "(minmax)", fortran.numerics.minmax + ) def init_all_module_vars(): diff --git a/process/main.py b/process/main.py index 5661643be2..eb2a3f5bbc 100644 --- a/process/main.py +++ b/process/main.py @@ -379,7 +379,6 @@ def run(self): This is separate from init to allow model instances to be modified before a run. """ self.validate_user_model() - self.run_tests() self.call_solver() self.run_scan(self.solver) self.finish() @@ -456,12 +455,6 @@ def initialise(): # [:n] as array always at max size: contains 0s fortran.numerics.ixc[:n].sort() - def run_tests(self): - """Run tests if required to by input file.""" - # TODO This would do better in a separate input validation module. - if fortran.global_variables.run_tests == 1: - fortran.main_module.runtests() - def call_solver(self): """Call the equation solver (HYBRD).""" # If no HYBRD (non-optimisation) runs are required, return diff --git a/source/fortran/main_module.f90 b/source/fortran/main_module.f90 deleted file mode 100644 index 839f422c9d..0000000000 --- a/source/fortran/main_module.f90 +++ /dev/null @@ -1,744 +0,0 @@ -#ifndef COMMSG -#error COMMSG not defined! -#endif - -#ifndef tagno -#error tagno not defined! -#endif - -#ifndef branch_name -#error branch_name not defined! -#endif - -#ifndef untracked -#error untracked not defined! -#endif - -module main_module - -#ifndef dp - use, intrinsic :: iso_fortran_env, only: dp=>real64 -#endif - - implicit none - -contains - -! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -subroutine inform(progid) - - !! Routine to obtain information about the program being executed - !! author: P J Knight, CCFE, Culham Science Centre - !! progid(0:10) : output string array : Strings containing useful info - !! This subroutine uses system calls to identify the user, date, - !! machine etc. for the present run, and stores the information - !! in a character string array. - !! ! - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - use constants, only: nout - implicit none - - ! Arguments - character(len=110), dimension(0:10) :: progid - - ! Local variables - character(len=10) :: progname - character(len=98) :: executable - character(len=*), parameter :: progver = & ! Beware: keep exactly same format... - '3.1.0 Release Date :: 2024-03-21' - character(len = 50) :: dt_time - character(len=72), dimension(10) :: id - - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - ! Program name - progname = 'PROCESS' - call get_command_argument(0, executable) - call get_DDMonYYTimeZone(dt_time) - id(1) = trim(dt_time) ! values(3)//"/"// values(2)//"/"// values(1) ! 5 6 7!date - call getlog(id(2)) ! Get user ID - call hostnm(id(3)) ! Get host name - call getcwd(id(4)) ! Get current working directory - - ! Annotate information and store in PROGID character array - ! for use in other program units via the routine argument - - progid(1) = ' Program : ' // executable - progid(2) = ' Version : ' // progver - progid(3) = 'Date/time : ' // id(1) - progid(4) = ' User : ' // id(2) - progid(5) = ' Computer : ' // id(3) - progid(6) = 'Directory : ' // id(4) - - ! Summarise most useful data, and store in progid(0) - progid(0) = trim(progname) // ' ' // trim(progver(:7)) // & - ' : Run on ' // trim(id(1)) // ' by ' // trim(id(3)) - -end subroutine inform - -! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -subroutine run_summary - - !! Routine to print out a summary header - !! author: P J Knight, CCFE, Culham Science Centre - !! None - !! This routine prints out a header summarising the program - !! execution details, plus a list of the active iteration - !! variables and constraint equations for the run. - !! A User's Guide to the PROCESS Systems Code, P. J. Knight, - !! AEA Fusion Report AEA FUS 251, 1993 - ! - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - use constants, only: nout, mfile, iotty, mfile - use maths_library, only: integer2string, integer3string - use global_variables, only: maxcal, fileprefix, icase, runtitle - use numerics, only: nvar, neqns, ioptimz, nineqns, epsvmc, minmax, icc, & - lablcc, lablmm - use process_output, only: ocentr, oblnkl, ocmmnt, ostars, ovarst, ovarin - use physics_variables, only: te - implicit none - - ! Local variables - integer, parameter :: width = 110 - integer :: lap, ii, outfile - character(len = 110) :: progid(0:10) - character(len = 9) :: vstring - character(len = 8) :: date - character(len = 10) :: time - character(len = 12) :: dstring - character(len = 7) :: tstring - character(len = 10) :: ustring - character(len = 100) :: rstring - character(len = 60) :: fom_string - character(len = 14) :: minmax_string - character(len = 10) :: eps_string - character :: minmax_sign - - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - ! Obtain execution details for this run - call inform(progid) - - ! Print code banner + run details to screen and output file - do lap = 1,2 - if (lap == 1) then - outfile = iotty - else - outfile = nout - end if - - ! PROCESS code header - call oblnkl(outfile) - call ostars(outfile, width) - call ocentr(outfile,'PROCESS', width) - call ocentr(outfile,'Power Reactor Optimisation Code', width) - call ostars(outfile, width) - call oblnkl(outfile) - - ! Run execution details - call ocmmnt(outfile, progid(1)) ! program name - call ocmmnt(outfile, progid(2)) ! version - if (untracked > 0) then ! tag number - call ocmmnt(outfile, ' Tag No. : '//tagno//' code contains untracked changes') - else - call ocmmnt(outfile, ' Tag No. : '//tagno) - end if - call ocmmnt(outfile, ' Branch : '//branch_name) - call ocmmnt(outfile, ' Git log : '// & - COMMSG) ! Last git com message - call ocmmnt(outfile, progid(3)) ! date/time - call ocmmnt(outfile, progid(4)) ! user - call ocmmnt(outfile, progid(5)) ! computer - call ocmmnt(outfile, progid(6)) ! directory - if (trim(fileprefix) == "") then - call ocmmnt(outfile, ' Input : IN.DAT') ! input file name - else - call ocmmnt(outfile, ' Input : '//trim(fileprefix)) ! input file name - end if - call ocmmnt(outfile, 'Run title : '//trim(runtitle)) ! run title - call ocmmnt(outfile, ' Run type : Reactor concept design: '// trim(icase) // ', (c) CCFE') - - call oblnkl(outfile) - call ostars(outfile, width) - call oblnkl(outfile) - call ocmmnt(outfile, ' Equality constraints : '//integer2string(neqns)) ! Number of equality constraints - call ocmmnt(outfile, 'Inequality constraints : '//integer2string(nineqns)) ! Number of inequality constraints - call ocmmnt(outfile, ' Total constraints : '//integer2string(neqns+nineqns)) ! Number of constraints - call ocmmnt(outfile, ' Iteration variables : '//integer2string(nvar)) ! Number of iteration variables - call ocmmnt(outfile, ' Max iterations : '//integer3string(maxcal)) ! Max number of iterations - - if (minmax > 0) then - minmax_string = ' -- minimise ' - minmax_sign = "+" - else - minmax_string = ' -- maximise ' - minmax_sign = "-" - end if - fom_string = lablmm(abs(minmax)) - call ocmmnt(outfile, ' Figure of merit : '//minmax_sign//integer2string(abs(minmax))//minmax_string//fom_string) ! Figure of merit - - write(eps_string, '(ES8.2)') epsvmc - call ocmmnt(outfile, ' Convergence parameter : '//eps_string) ! Convergence parameter - call oblnkl(outfile) - call ostars(outfile, width) - end do - - call oblnkl(outfile) - call ocmmnt(nout,'(Please include this header in any models, presentations and papers based on these results)') - call oblnkl(nout) - call ostars(nout, width) - ! Issue #270 - call oblnkl(outfile) - call ocmmnt(nout,'Quantities listed in standard row format are labelled as follows in columns 112-114:') - call ocmmnt(nout,'ITV : Active iteration variable (in any output blocks)') - call ocmmnt(nout,'OP : Calculated output quantity') - call ocmmnt(nout,'Unlabelled quantities in standard row format are generally inputs') - call ocmmnt(nout,'Note that calculated quantities may be trivially rescaled from inputs, or equal to bounds which are input.') - ! MDK Note that the label must be exactly three characters or none - I don't know how to fix this. - - ! Beware of possible future changes to the progid(...) layouts - - ! Relies on an internal read statement - vstring = progid(2)(13:21) - call ovarst(mfile,'PROCESS version number','(procver)','"'//vstring//'"') - - call date_and_time(date=date, time=time) - - ! Date output in the form "DD/MM/YYYY" (including quotes) - dstring = '"'//date(7:8)//'/'//date(5:6)//'/'//date(1:4)//'"' - call ovarst(mfile,'Date of run','(date)',dstring) - - ! Time output in the form "hh:mm" (including quotes) - tstring = '"'//time(1:2)//':'//time(3:4)//'"' - call ovarst(mfile,'Time of run','(time)',tstring) - - ustring = '"'//trim(progid(4)(13:20))//'"' - call ovarst(mfile,'User','(username)',ustring) - - rstring = '"'//runtitle//'"' - call ovarst(mfile,'PROCESS run title','(runtitle)',rstring) - - rstring = '"'//tagno//'"' - call ovarst(mfile,'PROCESS tag number','(tagno)',rstring) - - rstring = '"'//branch_name//'"' - call ovarst(mfile,'PROCESS git branch name','(branch_name)',rstring) - - rstring = '"'//COMMSG//'"' - call ovarst(mfile,'PROCESS last commit message','(commsg)',rstring) - - call ovarst(mfile,'Input filename','(fileprefix)','"'//trim(fileprefix//'"')) - - if (ioptimz == -2) then - call ovarin(mfile,'Optimisation switch','(ioptimz)',ioptimz) - call ovarin(mfile,'Figure of merit switch','(minmax)',minmax) - end if - -#ifndef unit_test - - ! MDK Only print out the constraints here for HYBRD. - ! For VMCON they are printed out later with residues. - call oblnkl(nout) - if (ioptimz == -1) then - call ocmmnt(nout, 'The following constraint equations have been imposed,') - call ocmmnt(nout, 'but limits will not be enforced by the code :') - write(nout,30) -30 format(t10,'icc',t25,'label') - call oblnkl(nout) - write(nout,40) (ii,icc(ii),lablcc(icc(ii)), ii=1,neqns+nineqns) -40 format(t1,i3,t10,i3,t18,a33) - end if - -#endif - -end subroutine run_summary - -! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -! Minpack Copyright Notice (1999) University of Chicago. All rights reserved - -! Redistribution and use in source and binary forms, with or -! without modification, are permitted provided that the -! following conditions are met: - -! 1. Redistributions of source code must retain the above -! copyright notice, this list of conditions and the following -! disclaimer. - -! 2. Redistributions in binary form must reproduce the above -! copyright notice, this list of conditions and the following -! disclaimer in the documentation and/or other materials -! provided with the distribution. - -! 3. The end-user documentation included with the -! redistribution, if any, must include the following -! acknowledgment: - -! "This product includes software developed by the -! University of Chicago, as Operator of Argonne National -! Laboratory. - -! Alternately, this acknowledgment may appear in the software -! itself, if and wherever such third-party acknowledgments -! normally appear. - -! 4. WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS" -! WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE -! UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND -! THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR -! IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES -! OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE -! OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY -! OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR -! USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF -! THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4) -! DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION -! UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL -! BE CORRECTED. - -! 5. LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT -! HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF -! ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT, -! INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF -! ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF -! PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER -! SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT -! (INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE, -! EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE -! POSSIBILITY OF SUCH LOSS OR DAMAGES. - -! eqslv() has been temporarily commented out. Please see the comment in -! function_evaluator.fcnhyb() for an explanation. - -! subroutine eqslv(ifail) - -! !! Routine to call the non-optimising equation solver -! !! author: P J Knight, CCFE, Culham Science Centre -! !! ifail : output integer : error flag -! !! This routine calls the non-optimising equation solver. -! !! ! ! -! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -! use constants, only: nout, mfile, iotty -! use constraints, only: constraint_eqns -! use function_evaluator, only: fcnhyb -! use error_handling, only: idiags, fdiags, errors_on, report_error -! use numerics, only: ipeqns, epsfcn, factor, ftol, iptnt, ncalls, & -! neqns, nfev1, nfev2, sqsumsq, xcm, rcm, xcs, resdl, scafc, ixc, lablxc, & -! icc, lablcc, eqsolv -! use process_output, only: ovarin, oblnkl, ocmmnt, oheadr, osubhd, & -! ovarre, int_to_string3 -! use physics_variables, only: bt, aspect, rmajor, fusion_power, wallmw -! use define_iteration_variables, only: loadxc -! implicit none - -! ! Arguments -! integer, intent(out) :: ifail - -! ! Local variables -! integer :: inn,nprint,nx -! real(dp) :: sumsq -! ! real(dp), dimension(iptnt) :: wa -! real(dp) :: wa(iptnt) -! real(dp), dimension(ipeqns) :: con1, con2, err -! character(len = 1), dimension(ipeqns) :: sym -! character(len = 10), dimension(ipeqns) :: lab - -! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -! ncalls = 0 -! nfev1 = 0 -! nfev2 = 0 -! nprint = 0 - -! ! Use HYBRD to find a starting point -! call loadxc -! call eqsolv(fcnhyb,neqns,xcm,rcm,ftol,epsfcn,factor,nprint,ifail, & -! wa,iptnt,resdl,nfev1) - -! ! Turn on error reporting -! errors_on = .true. - -! ! Print out information on solution -! call oheadr(nout,'Numerics') -! call ocmmnt(nout, & -! 'PROCESS has performed a HYBRD (non-optimisation) run,') - -! if (ifail /= 1) then -! call ocmmnt(nout,'but could NOT find a feasible set of parameters.') -! call oblnkl(nout) -! call ovarin(nout,'Number of iteration variables and constraints','(neqns)',neqns) -! call ovarin(nout,'HYBRD error flag','(ifail)',ifail) - -! call oheadr(iotty,'PROCESS COULD NOT FIND A FEASIBLE SOLUTION') -! call ovarin(iotty,'HYBRD error flag (ifail)','',ifail) -! call oblnkl(iotty) - -! idiags(1) = ifail ; call report_error(131) - -! else -! call ocmmnt(nout,'and found a feasible set of parameters.') -! call oblnkl(nout) -! call ovarin(nout,'HYBRD error flag','(ifail)',ifail) -! call oblnkl(nout) -! call oheadr(iotty,'PROCESS found a feasible solution') -! end if - -! ! Sum the square of the residuals -! sumsq = 0.0D0 -! do nx = 1,neqns -! sumsq = sumsq + rcm(nx)**2 -! end do -! sqsumsq = sqrt(sumsq) - -! call ovarre(nout,'Square root of the sum of squares of the constraint residuals','(sqsumsq)',sqsumsq, 'OP ') - -! ! If necessary, write out a relevant error message -! if (ifail /= 1) then -! call oblnkl(nout) -! call herror(ifail) -! call oblnkl(iotty) -! else -! ! Show a warning if the constraints appear high even if allegedly converged -! if (sqsumsq >= 1.0D-2) then -! call oblnkl(nout) -! call ocmmnt(nout,'WARNING: Constraint residues are HIGH; consider re-running') -! call ocmmnt(nout,' with lower values of FTOL to confirm convergence...') -! call ocmmnt(nout,' (should be able to get down to about 1.0E-8 okay)') - -! call ocmmnt(iotty,'WARNING: Constraint residues are HIGH; consider re-running') -! call ocmmnt(iotty,' with lower values of FTOL to confirm convergence...') -! call ocmmnt(iotty,' (should be able to get down to about 1.0E-8 okay)') -! call oblnkl(iotty) - -! fdiags(1) = sqsumsq ; call report_error(133) - -! end if -! end if - -! call osubhd(nout,'The solution vector is comprised as follows :') - -! write(nout,10) -! 10 format(t5,'i',t23,'final',t33,'fractional',t46,'residue') - -! write(nout,20) -! 20 format(t23,'value',t35,'change') - -! call oblnkl(nout) - -! do inn = 1,neqns -! xcs(inn) = xcm(inn)*scafc(inn) -! write(nout,30) inn,lablxc(ixc(inn)),xcs(inn),xcm(inn),resdl(inn) -! call ovarre(mfile,lablxc(ixc(inn)),'(itvar'//int_to_string3(inn)//')',xcs(inn)) -! end do -! !30 format(t2,i4,t8,a9,t19,1pe12.4,1pe12.4,1pe12.4) -! ! Make lablxc longer -! 30 format(t2,i4,t8,a30,t39,1pe12.4,1pe12.4,1pe12.4) - -! call osubhd(nout, & -! 'The following constraint residues should be close to zero :') - -! call constraint_eqns(neqns,con1,-1,con2,err,sym,lab) -! write(nout,40) -! 40 format(t48,'physical',t73,'constraint',t100,'normalised') -! write(nout,50) -! 50 format(t47,'constraint',t74,'residue',t101,'residue') -! call oblnkl(nout) -! do inn = 1,neqns -! write(nout,60) inn,lablcc(icc(inn)),sym(inn),con2(inn), & -! lab(inn),err(inn),lab(inn),con1(inn) -! call ovarre(mfile,lablcc(icc(inn))//' normalised residue', & -! '(normres'//int_to_string3(inn)//')',con1(inn)) -! end do -! 60 format(t2,i4,t8,a33,t46,a1,t47,1pe12.4,t60,a10,t71,1pe12.4,t84,a10,t98,1pe12.4) - -! end subroutine eqslv - -! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -subroutine herror(ifail) - - !! Routine to print out relevant messages in the case of an - !! unfeasible result from a HYBRD (non-optimisation) run - !! author: P J Knight, CCFE, Culham Science Centre - !! ifail : input integer : error flag - !! This routine prints out relevant messages in the case of - !! an unfeasible result from a HYBRD (non-optimisation) run. - !!

The messages are written to units NOUT and IOTTY, which are - !! by default the output file and screen, respectively. - !!

If IFAIL=1 then a feasible solution has been - !! found and therefore no error message is required. - !! ! - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - use constants, only: nout, iotty - use process_output, only: oblnkl, ocmmnt - implicit none - - ! Arguments - integer, intent(in) :: ifail - - ! Local variables - - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - select case (ifail) - - case (:-1) - call ocmmnt(nout, 'User-terminated execution of HYBRD.') - call ocmmnt(iotty,'User-terminated execution of HYBRD.') - - case (0) - call ocmmnt(nout, 'Improper input parameters to the HYBRD routine.') - call ocmmnt(nout, 'PROCESS coding must be checked.') - - call ocmmnt(iotty,'Improper input parameters to the HYBRD routine.') - call ocmmnt(iotty,'PROCESS coding must be checked.') - - case (1) - continue - - case (2) - call ocmmnt(nout,'The maximum number of calls has been reached without solution,') - call ocmmnt(nout,'suggesting that the iteration is not making good progress.') - call ocmmnt(nout,'Try changing the variables in IXC.') - - call ocmmnt(iotty,'The maximum number of calls has been reached without solution,') - call ocmmnt(iotty,'suggesting that the iteration is not making good progress.') - call ocmmnt(iotty,'Try changing the variables in IXC.') - - case (3) - call ocmmnt(nout,'The tolerance is too small: No further improvement in the approximate solution is possible.') - call ocmmnt(nout,'Try raising the value of FTOL.') - - call ocmmnt(iotty, 'The tolerance is too small: No further improvement in the approximate solution is possible.') - call ocmmnt(iotty,'in the approximate solution is possible.') - call ocmmnt(iotty,'Try raising the value of FTOL.') - - case (4) - call ocmmnt(nout,'The iteration is not making good progress.') - call ocmmnt(nout,'The code may be stuck in a minimum in the residual') - call ocmmnt(nout,'space that is significantly above zero.') - call oblnkl(nout) - call ocmmnt(nout,'There is either no solution possible, or the code') - call ocmmnt(nout,'is failing to escape from a deep local minimum.') - call ocmmnt(nout,'Try changing the variables in IXC, or modify their initial values.') - - call ocmmnt(iotty,'The iteration is not making good progress.') - call ocmmnt(iotty,'The code may be stuck in a minimum in the residual') - call ocmmnt(iotty,'space that is significantly above zero.') - call oblnkl(iotty) - call ocmmnt(iotty,'There is either no solution possible, or the code') - call ocmmnt(iotty,'is failing to escape from a deep local minimum.') - call ocmmnt(iotty,'Try changing the variables in IXC, or modify their initial values.') - - case default - call ocmmnt(nout,'This value of IFAIL should not be possible...') - call ocmmnt(nout,'See source code for details.') - - call ocmmnt(iotty,'This value of IFAIL should not be possible...') - call ocmmnt(iotty,'See source code for details.') - - end select - -end subroutine herror - -! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -subroutine verror(ifail) - - !! Routine to print out relevant messages in the case of an - !! unfeasible result from a VMCON (optimisation) run - !! author: P J Knight, CCFE, Culham Science Centre - !! ifail : input integer : error flag - !! This routine prints out relevant messages in the case of - !! an unfeasible result from a VMCON (optimisation) run. - !!

The messages are written to units NOUT and IOTTY, which are - !! by default the output file and screen, respectively. - !!

If IFAIL=1 then a feasible solution has been - !! found and therefore no error message is required. - !! ! - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - use constants, only: nout, iotty - use process_output, only: ocmmnt, oblnkl - implicit none - - ! Arguments - integer, intent(in) :: ifail - - ! Local variables - - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - select case (ifail) - - case (:-1) - call ocmmnt(nout, 'User-terminated execution of VMCON.') - call ocmmnt(iotty,'User-terminated execution of VMCON.') - - case (0) - call ocmmnt(nout, 'Improper input parameters to the VMCON routine.') - call ocmmnt(nout, 'PROCESS coding must be checked.') - - call ocmmnt(iotty,'Improper input parameters to the VMCON routine.') - call ocmmnt(iotty,'PROCESS coding must be checked.') - - case (1) - continue - - case (2) - call ocmmnt(nout,'The maximum number of calls has been reached without solution.') - call ocmmnt(nout,'The code may be stuck in a minimum in the residual space that is significantly above zero.') - call oblnkl(nout) - call ocmmnt(nout,'There is either no solution possible, or the code') - call ocmmnt(nout,'is failing to escape from a deep local minimum.') - call ocmmnt(nout,'Try changing the variables in IXC, or modify their initial values.') - - call ocmmnt(iotty,'The maximum number of calls has been reached without solution.') - call ocmmnt(iotty,'The code may be stuck in a minimum in the residual space that is significantly above zero.') - call oblnkl(nout) - call oblnkl(iotty) - call ocmmnt(iotty,'There is either no solution possible, or the code') - call ocmmnt(iotty,'is failing to escape from a deep local minimum.') - call ocmmnt(iotty,'Try changing the variables in IXC, or modify their initial values.') - - case (3) - call ocmmnt(nout,'The line search required the maximum of 10 calls.') - call ocmmnt(nout,'A feasible solution may be difficult to achieve.') - call ocmmnt(nout,'Try changing or adding variables to IXC.') - - call ocmmnt(iotty,'The line search required the maximum of 10 calls.') - call ocmmnt(iotty,'A feasible solution may be difficult to achieve.') - call ocmmnt(iotty,'Try changing or adding variables to IXC.') - - case (4) - call ocmmnt(nout,'An uphill search direction was found.') - call ocmmnt(nout,'Try changing the equations in ICC, or') - call ocmmnt(nout,'adding new variables to IXC.') - - call ocmmnt(iotty,'An uphill search direction was found.') - call ocmmnt(iotty,'Try changing the equations in ICC, or') - call ocmmnt(iotty,'adding new variables to IXC.') - - case (5) - call ocmmnt(nout, & - 'The quadratic programming technique was unable to') - call ocmmnt(nout,'find a feasible point.') - call oblnkl(nout) - call ocmmnt(nout,'Try changing or adding variables to IXC, or modify') - call ocmmnt(nout,'their initial values (especially if only 1 optimisation') - call ocmmnt(nout,'iteration was performed).') - - call ocmmnt(iotty, & - 'The quadratic programming technique was unable to') - call ocmmnt(iotty,'find a feasible point.') - call oblnkl(iotty) - call ocmmnt(iotty,'Try changing or adding variables to IXC, or modify') - call ocmmnt(iotty,'their initial values (especially if only 1 optimisation') - call ocmmnt(iotty,'iteration was performed).') - - case (6) - call ocmmnt(nout, & - 'The quadratic programming technique was restricted') - call ocmmnt(nout, & - 'by an artificial bound, or failed due to a singular') - call ocmmnt(nout,'matrix.') - call ocmmnt(nout,'Try changing the equations in ICC, or') - call ocmmnt(nout,'adding new variables to IXC.') - - call ocmmnt(iotty, & - 'The quadratic programming technique was restricted') - call ocmmnt(iotty, & - 'by an artificial bound, or failed due to a singular') - call ocmmnt(iotty,'matrix.') - call ocmmnt(iotty,'Try changing the equations in ICC, or') - call ocmmnt(iotty,'adding new variables to IXC.') - - case default - call ocmmnt(nout,'This value of IFAIL should not be possible...') - call ocmmnt(nout,'See source code for details.') - - call ocmmnt(iotty,'This value of IFAIL should not be possible...') - call ocmmnt(iotty,'See source code for details.') - - end select - -end subroutine verror - -! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - - - -subroutine runtests - ! These tests should gradually be moved to pytest - use constants, only: nout - use maths_library, only: binomial - use process_output, only: ocmmnt, ovarre -! use pfcoil_module, only: brookscoil -! use reinke_module, only: test_reinke - implicit none - real(dp) :: fshift, xf, enpa,ftherm,fpp,cdeff, ampperwatt - logical :: Temperature_capped - call ovarre(nout,'Binomial coefficients C(5,0): 1', '(binomial(5,0))', binomial(5,0)) - call ovarre(nout,'Binomial coefficients C(5,1): 5', '(binomial(5,1))', binomial(5,1)) - call ovarre(nout,'Binomial coefficients C(5,2): 10', '(binomial(5,2))', binomial(5,2)) - call ovarre(nout,'Binomial coefficients C(5,3): 10', '(binomial(5,3))', binomial(5,3)) - call ovarre(nout,'Binomial coefficients C(5,4): 5', '(binomial(5,4))', binomial(5,4)) - call ovarre(nout,'Binomial coefficients C(5,5): 1', '(binomial(5,5))', binomial(5,5)) - - ! call brookscoil(nout) Moved to pytest - ! Disabled for ease of #1542 - Tim -! call test_reinke() -end subroutine runtests - - -subroutine get_DDMonYYTimeZone(dt_time) - !! Routine to get date, time and timezone - !! author: M Kumar, CCFE, Culham Science Centre - !! dt_time : output string : String containing formatted time and date - !! This routine calls the intrinsic DATE_AND_TIME subroutine - !! and format the output in - !! DD Mon YYYY hr:minute:second time difference from UTC. - -! Arguments - CHARACTER(len = *), INTENT(OUT) :: dt_time -! Local variables - INTEGER :: values(8) - CHARACTER(len = 1), parameter :: tspt = ":" - CHARACTER(len = 1), parameter :: spspt = " " - - CHARACTER(len = 2) :: dd - CHARACTER(len = 5) :: mons(12) - CHARACTER(len = 4) :: yyyy - CHARACTER(len = 2) :: hr ! Hour of the day - CHARACTER(len = 2) :: mnt ! Minute of the hour - CHARACTER(len = 2) :: scnd ! The seconds of the minute - CHARACTER(len = 5) :: zn ! In form (+-)hhmm, representing the difference with respect to Coordinated Universal Time (UTC). - CHARACTER(len = 20) :: znfrmt - - mons = [' Jan ',' Feb ',' Mar ',' Apr ',' May ',' Jun ',& - ' Jul ',' Aug ',' Sep ',' Oct ',' Nov ',' Dec '] - - CALL DATE_AND_TIME(ZONE = zn, VALUES = values) - znfrmt = zn(1:3)//":"//zn(4:5)//"(hh:mm) UTC" - znfrmt = trim(znfrmt) - WRITE( dd,'(i2)') values(3) - WRITE(yyyy,'(i4)') values(1) - write(hr, '(i2)') values(5) - write(mnt, '(i2)') values(6) - write(scnd, '(i2)') values(7) - if(mnt(1:1) == " ") mnt(1:1) = "0" - if(scnd(1:1) == " ") scnd(1:1) = "0" - - dt_time = dd//mons(values(2))//yyyy//spspt// & - hr//tspt//mnt//tspt//scnd//spspt//znfrmt - dt_time = trim(dt_time) - - END subroutine get_DDMonYYTimeZone - -end module main_module diff --git a/source/fortran/scan.f90 b/source/fortran/scan.f90 index 161c59a102..3aa7fcf6b1 100644 --- a/source/fortran/scan.f90 +++ b/source/fortran/scan.f90 @@ -872,7 +872,6 @@ subroutine post_optimise(ifail) use numerics use process_output use utilities, only:upper_case - use main_module, only:verror ! for ipedestal = 2 option use global_variables, only: convergence_parameter use constants, only: iotty, nout, mfile @@ -1112,4 +1111,126 @@ end subroutine post_optimise ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +subroutine verror(ifail) + + !! Routine to print out relevant messages in the case of an + !! unfeasible result from a VMCON (optimisation) run + !! author: P J Knight, CCFE, Culham Science Centre + !! ifail : input integer : error flag + !! This routine prints out relevant messages in the case of + !! an unfeasible result from a VMCON (optimisation) run. + !!

The messages are written to units NOUT and IOTTY, which are + !! by default the output file and screen, respectively. + !!

If IFAIL=1 then a feasible solution has been + !! found and therefore no error message is required. + !! ! + ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + use constants, only: nout, iotty + use process_output, only: ocmmnt, oblnkl + implicit none + + ! Arguments + integer, intent(in) :: ifail + + ! Local variables + + ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + select case (ifail) + + case (:-1) + call ocmmnt(nout, 'User-terminated execution of VMCON.') + call ocmmnt(iotty,'User-terminated execution of VMCON.') + + case (0) + call ocmmnt(nout, 'Improper input parameters to the VMCON routine.') + call ocmmnt(nout, 'PROCESS coding must be checked.') + + call ocmmnt(iotty,'Improper input parameters to the VMCON routine.') + call ocmmnt(iotty,'PROCESS coding must be checked.') + + case (1) + continue + + case (2) + call ocmmnt(nout,'The maximum number of calls has been reached without solution.') + call ocmmnt(nout,'The code may be stuck in a minimum in the residual space that is significantly above zero.') + call oblnkl(nout) + call ocmmnt(nout,'There is either no solution possible, or the code') + call ocmmnt(nout,'is failing to escape from a deep local minimum.') + call ocmmnt(nout,'Try changing the variables in IXC, or modify their initial values.') + + call ocmmnt(iotty,'The maximum number of calls has been reached without solution.') + call ocmmnt(iotty,'The code may be stuck in a minimum in the residual space that is significantly above zero.') + call oblnkl(nout) + call oblnkl(iotty) + call ocmmnt(iotty,'There is either no solution possible, or the code') + call ocmmnt(iotty,'is failing to escape from a deep local minimum.') + call ocmmnt(iotty,'Try changing the variables in IXC, or modify their initial values.') + + case (3) + call ocmmnt(nout,'The line search required the maximum of 10 calls.') + call ocmmnt(nout,'A feasible solution may be difficult to achieve.') + call ocmmnt(nout,'Try changing or adding variables to IXC.') + + call ocmmnt(iotty,'The line search required the maximum of 10 calls.') + call ocmmnt(iotty,'A feasible solution may be difficult to achieve.') + call ocmmnt(iotty,'Try changing or adding variables to IXC.') + + case (4) + call ocmmnt(nout,'An uphill search direction was found.') + call ocmmnt(nout,'Try changing the equations in ICC, or') + call ocmmnt(nout,'adding new variables to IXC.') + + call ocmmnt(iotty,'An uphill search direction was found.') + call ocmmnt(iotty,'Try changing the equations in ICC, or') + call ocmmnt(iotty,'adding new variables to IXC.') + + case (5) + call ocmmnt(nout, & + 'The quadratic programming technique was unable to') + call ocmmnt(nout,'find a feasible point.') + call oblnkl(nout) + call ocmmnt(nout,'Try changing or adding variables to IXC, or modify') + call ocmmnt(nout,'their initial values (especially if only 1 optimisation') + call ocmmnt(nout,'iteration was performed).') + + call ocmmnt(iotty, & + 'The quadratic programming technique was unable to') + call ocmmnt(iotty,'find a feasible point.') + call oblnkl(iotty) + call ocmmnt(iotty,'Try changing or adding variables to IXC, or modify') + call ocmmnt(iotty,'their initial values (especially if only 1 optimisation') + call ocmmnt(iotty,'iteration was performed).') + + case (6) + call ocmmnt(nout, & + 'The quadratic programming technique was restricted') + call ocmmnt(nout, & + 'by an artificial bound, or failed due to a singular') + call ocmmnt(nout,'matrix.') + call ocmmnt(nout,'Try changing the equations in ICC, or') + call ocmmnt(nout,'adding new variables to IXC.') + + call ocmmnt(iotty, & + 'The quadratic programming technique was restricted') + call ocmmnt(iotty, & + 'by an artificial bound, or failed due to a singular') + call ocmmnt(iotty,'matrix.') + call ocmmnt(iotty,'Try changing the equations in ICC, or') + call ocmmnt(iotty,'adding new variables to IXC.') + + case default + call ocmmnt(nout,'This value of IFAIL should not be possible...') + call ocmmnt(nout,'See source code for details.') + + call ocmmnt(iotty,'This value of IFAIL should not be possible...') + call ocmmnt(iotty,'See source code for details.') + + end select + +end subroutine verror + end module scan_module diff --git a/tests/unit/test_main.py b/tests/unit/test_main.py index 61dab2064d..d618750bd1 100644 --- a/tests/unit/test_main.py +++ b/tests/unit/test_main.py @@ -215,23 +215,6 @@ def test_initialise(single_run, monkeypatch): single_run.initialise() -def test_run_tests(single_run, monkeypatch): - """Check main_module.runtests() is run if run_tests == 1. - - :param single_run: single_run fixture - :type single_run: SingleRun - :param monkeypatch: monkeypatch fixture - :type monkeypatch: object - """ - # TODO Can't actually check that this is being run yet; need a result that - # can be checked in the Python (isolated fixtures), to avoid side-effects - # persisting in the Fortran - # For now, just check that no exceptions are thrown before calling into - # the Fortran - monkeypatch.setattr(fortran.global_variables, "run_tests", 1) - single_run.run_tests() - - def test_call_solver(single_run, monkeypatch): """Attempt to call the hybrd() non-optimising solver.