The Doxygen
documentation for the main branch of Octopus can be found here.
It is automatically generated at a push to the main branch.
Currently, the links to the source code are broken and will most likely point to a wrong part of the file.
Running doxygen locally
To build the Doxygen
pages locally, go into the folder doc/doxygen/
inside the Octopus tree, and run the command
./create_documentation.sh
This might take a few minutes to complete. In case you need to rebuild the pages more often while writing new documentation, you might want to disable the creation of call graphs, by hanging the line
HAVE_DOT = YES
to
HAVE_DOT = NO
in the file Doxyfile
.
Writing documentation
There are several ways how to include comments into the Fortran source, which are shown in the following code snippet:
In particular, we would like to have documentation of modules, classes, and subroutines/functions, together with their data members and arguments.
General remarks about Doxygen
Doxygen
markers in Fortran are !>, !< and !!. The first two denote the beginning of a Doxygen
comment,
and the direction of the ‘arrow’ indicates what the comment refers to. In general, if a comment is before the
quantity which should be documented, one should use !>, while if the comment is at the end of the line
(e.g. for an function argument), one should use !<. Continuation lines use the !! marker.
Using the wrong marker can lead to wrong and confusing documentation.
A continuation of a comment to a function argument, written as
integer,intent(in)::dim!< Dimension of space
!! needs to be in the range 1 to 4.
is not accepted by findent-octopus
and will lead to a failing test.
Instead, this should be written as
integer,intent(in)::dim!< Dimension of space
!! needs to be in the range 1 to 4.
Markdown and Equations in Doxygen
Doxygen
supports Markdown syntax for formatting text. More details can be found here.
Furthermore, we enabled MathJax, which allows to use LaTeX formatted equations in the code documentation.
Mathematical formulas have to be enclosed by a pair of \f$ for inline formulas, or by the pair of \f[ and \f]
for formulas to be displayed as separate line. See https://www.doxygen.nl/manual/formulas.html.
Module documentation
Before the declaration of the module, there should be a block
!> @brief This modules implements ...
!!
!! Some more details about the modules, how it is related to the code, general theory,
!! references to papers, etc.
!!
modulemodule1_oct_m...endmodule
There is one peculiarity about the Doxygen usage in Octopus, which is that we need to pass the sources through
the cpp preprocessor in order to handle some macros, in particular out poor-man’s templating. This has the
side effect that the preprocessor removes all C/C++ like comments from the code, including the ‘//’ in URLs.
URLs can be included in Doxygen comments by using the HTTP and HTTPS macros.
!> @brief The Octopus code
!!
!! The web documentation can be accessed \HTTPS{here,octopus-code.org}.
!!
Class documentation
Before the declaration of the module, there should be a block
!> @brief This class implements ..
!!
!! Some more details about the class, which is not in the module description
!! or in the documentation of member data or procedure
!!
typeclass1_tprivateclass(system_t)::system!< This system is related to the current object
logical,public::is_initialized!< indicates whether all initialization has been successfully done
...contains! Below are the methods, the class implements
procedure::do_something=>class1_do_something!< @copydoc module1_oct_m::class1_do_something
procedure::finished=>class1_finished!< @copydoc module1_oct_m::class1_finished
...endtype
The @copydoc command here instructs
Doxygen
to copy the documentation from the actual function definition for the class method.
Note that the corresponding module name has to be prepended (in C++ codes, this would be the namespace).
Subroutine / Function documentation
The documentation of functions and subroutines is similar to that of classes.
Example
Example
!! Copyright (C) 2019 N. Tancogne-Dejean
!! Copyright (C) 2020 M. Oliveira
!!
!! This program is free software; you can redistribute it and/or modify
!! it under the terms of the GNU General Public License as published by
!! the Free Software Foundation; either version 2, or (at your option)
!! any later version.
!!
!! This program is distributed in the hope that it will be useful,
!! but WITHOUT ANY WARRANTY; without even the implied warranty of
!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
!! GNU General Public License for more details.
!!
!! You should have received a copy of the GNU General Public License
!! along with this program; if not, write to the Free Software
!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
!! 02110-1301, USA.
!!
#include "global.h"
!> @brief This module implements the basic propagator framework.
!!
modulepropagator_oct_musealgorithm_oct_museclock_oct_musedebug_oct_museglobal_oct_museiteration_counter_oct_musemessages_oct_musenamespace_oct_musesystem_oct_mimplicitnoneprivatepublic::&propagator_t!> @brief Abstract class implementing propagators
!!
!! Propagators are implemented as a state machine. This abstract class defines the steps which
!! are independent of the actual propatation algorithm, and also independent of the system, to
!! which is is applied.
type,extends(algorithm_t),abstract::propagator_tprivateclass(system_t),pointer,public::system!< The system using this propagator
type(algorithm_iterator_t)::scf_start!< If the algorithm contains a self-consistency loop,
!! we need to save the start of that loop to be able to
!! jump back to it.
real(real64),public::dt!< Physical duration of one time step
real(real64),public::final_time=M_ZERO!< The final time of the simulation.
! Options related to predictor-corrector propagators
logical,public::inside_scf=.false.!< Indicate whether the system is executing an SCF loop
logical,public::predictor_corrector=.false.integer,public::scf_count!< Counter for self-consistency iterations
integer,public::max_scf_count!< Maximum number of iterations for self-consistent propagators
integer,public::accumulated_loop_ticksreal(real64),public::scf_tol!< Tolerance for self-consistent propagators
contains! Below are the list of operations that needs to be implemented
procedure::do_operation=>propagator_do_operation!< @copydoc propagator_do_operation
procedure::finished=>propagator_finished!< @copydoc propagator_finished
procedure::init_iteration_counters=>propagator_init_iteration_counters!< @copydoc propagator_init_iteration_counters
procedure::save_scf_start=>propagator_save_scf_start!< @copydoc propagator_save_scf_start
procedure::rewind_scf_loop=>propagator_rewind_scf_loop!< @copydoc propagator_rewind_scf_loop
endtypepropagator_t!# doc_start general_propagation_operations
! Known propagation operations
character(len=ALGO_LABEL_LEN),public,parameter::&START_SCF_LOOP='START_SCF_LOOP',&END_SCF_LOOP='END_SCF_LOOP',&STORE_CURRENT_STATUS='STORE_CURRENT_STATUS'type(algorithmic_operation_t),public,parameter::&OP_START_SCF_LOOP=algorithmic_operation_t(START_SCF_LOOP,'Starting SCF loop'),&OP_END_SCF_LOOP=algorithmic_operation_t(END_SCF_LOOP,'End of SCF iteration'),&OP_STORE_CURRENT_STATUS=algorithmic_operation_t(STORE_CURRENT_STATUS,'Store current status')!# doc_end
contains!> @brief Try to perform one operation of the algorithm. Return .true. if sucessful.
!!
logicalfunctionpropagator_do_operation(this,operation)result(done)class(propagator_t),intent(inout)::thistype(algorithmic_operation_t),intent(in)::operationdone=.true.selectcase(operation%id)case(UPDATE_INTERACTIONS)! Update the accumulated loop ticks before executing this generic operation
this%accumulated_loop_ticks=this%accumulated_loop_ticks+1done=.false.case(START_SCF_LOOP)ASSERT(this%predictor_corrector)callthis%save_scf_start()this%inside_scf=.true.this%accumulated_loop_ticks=0if(debug%info)thenwrite(message(1),'(a,i3,a)')"Debug: -- SCF iter ",this%scf_count," for '"+trim(this%system%namespace%get())+"'"callmessages_info(1,namespace=this%system%namespace)endifcase(END_SCF_LOOP)! Here we first check if we did the maximum number of steps.
! Otherwise, we need check the tolerance
if(this%scf_count==this%max_scf_count)thenif(debug%info)thenmessage(1)="Debug: -- Max SCF Iter reached for '"+trim(this%system%namespace%get())+"'"callmessages_info(1,namespace=this%system%namespace)endifthis%inside_scf=.false.callthis%next()else! We reset the pointer to the beginning of the scf loop
if(this%system%is_tolerance_reached(this%scf_tol))thenif(debug%info)thenmessage(1)="Debug: -- SCF tolerance reached for '"+trim(this%system%namespace%get())+"'"callmessages_info(1,namespace=this%system%namespace)endifthis%inside_scf=.false.callthis%next()else! We rewind the instruction stack
callthis%rewind_scf_loop()! We reset the clocks
callthis%system%reset_iteration_counters(this%accumulated_loop_ticks)this%accumulated_loop_ticks=0if(debug%info)thenwrite(message(1),'(a,i3,a,a)')"Debug: -- SCF iter ",this%scf_count," for '"+trim(this%system%namespace%get()),"'"callmessages_info(1,namespace=this%system%namespace)endifendifendifcasedefaultdone=.false.endselectendfunctionpropagator_do_operation! ---------------------------------------------------------
!> @brief indicate whether a propagation has reached the final time
!!
logicalfunctionpropagator_finished(this)class(propagator_t),intent(in)::thistype(iteration_counter_t)::clock_clock_=this%system%iteration+1propagator_finished=clock_%value()>this%final_timeendfunctionpropagator_finished! ---------------------------------------------------------
!> Initialize the propagator and system clocks.
!!
!! Note that we initialize the system clock here because it requires knowledge
!! of the time-step.
subroutinepropagator_init_iteration_counters(this)class(propagator_t),intent(inout)::thisthis%iteration=clock_t(time_step=this%dt/this%algo_steps)this%system%iteration=clock_t(time_step=this%dt)endsubroutinepropagator_init_iteration_counters!> @brief Save the current iteration state (START_SCF_LOOP) and move to next step
!
subroutinepropagator_save_scf_start(this)class(propagator_t),intent(inout)::thisPUSH_SUB(propagator_save_scf_start)this%scf_start=this%itercallthis%next()this%scf_count=0POP_SUB(propagator_save_scf_start)endsubroutinepropagator_save_scf_start! ---------------------------------------------------------
!> @brief Reset the iteration state to the beginning of the loop (START_SCF_LOOP) and move to next step
!
subroutinepropagator_rewind_scf_loop(this)class(propagator_t),intent(inout)::thisPUSH_SUB(propagator_rewind_scf_loop)this%iter=this%scf_startcallthis%next()this%scf_count=this%scf_count+1POP_SUB(propagator_rewind_scf_loop)endsubroutinepropagator_rewind_scf_loopendmodulepropagator_oct_m!! Local Variables:
!! mode: f90
!! coding: utf-8
!! End: