Contributing

Your contributions to the mmg project are welcome. You can help us to improve our code by many means:

Pull requests

To contribute to mmg through bug fixes or feature development, please read the following guidelines.

I/ Read carefully and agree to the following paragraph

For your work to be included in the project, please:

  • agree and fill the corporate contributor agreement if the intellectual property of the contributed code belongs to your employer or the individual contributor agreement if it belongs to you, both available here.

  • ask first before implementing any features.

  • do not perform code refactoring.

  • adopt our coding conventions:

    • use our indentation convention (2 spaces instead of tabulations).

    • do not add non significant white spaces (trailing white spaces or white spaces on blank line).

    • limit the size of your lines to 80 characters;

    • try to modify only things relevant with your PR (do not indent an entire file, even if needed, for example).

    • write accurate Doxygen comments (see for example the documentation of the

    • declaration of variables in the top of the function;

    • do not use exit(), use a return value instead;

    • do not implement void API functions;

    • the main library functions returns MMG<X>_SUCCESS if successful, MMG<X>_LOWFAILURE if the function fails but we can save the mesh, and MMG<X>_STRONGFAILURE if fails and we can’t save a conforming mesh. API_functions.c file).

    • write accurate commit messages.

    • run the continuous integration test before opening any pull request.

  • agree to license your work under the GNU Lesser General Public License.

II/ Software contribution

To contribute to the mmg software:

  • Fork the project on GitHub and clone your fork:

    git clone https://github.com/<username>/mmg
    
  • Assign the original mmg repository to a remote named upstream:

    git remote add upstream https://github.com/MmgTools/mmg
    
  • Note that you can check your remote with git remote -v. You will need to fetch the upstream branch:

    git fetch upstream
    
  • Create a new develop branch that points towards the MmgTools/mmg develop branch:

    git checkout -b develop upstream/develop
    
  • Create a new branch for your feature from the develop branch:

    git checkout -b feature/myFeature develop
    
  • If you want, you can push your feature branch up to your repository:

    git push origin feature/myfeature
    
  • To avoid painful merge after huge modifications, do not forget to regularly get the modifications of the upstream develop into your develop branch and to merge this into your feature branch:

    git checkout develop
    git pull upstream develop
    git checkout feature/myFeature
    git merge develop
    
  • Open a pull request with a title and a detailed description.

Documenting your code using Doxygen

I/ How

General case

Our project use Doxygen to automatically generate the developer documentation. If you implement a new function in mmg, comment it and give at least its interface description (function arguments and return values).

For example a minimal documentation for the function that saves the mesh may be this one:

/**
* \param mesh  pointer to the mesh structure.
* \param filename  pointer to the name of the file.
* \return 0 if failed, 1 otherwise.
*
* Save mesh data.
*
* \warning you must call the \a _MMG3D_packMesh function before saving your
* mesh.
*/
int MMG3D_saveMesh(MMG5_pMesh mesh, char *filename);

Additionally, it is good practice to include text inside the routine to explain the work carried out.

You can refer to the Doxygen documentation for a description of the Doxygen commands.

API functions

Because the library header for Fortran users is automatically generated from the C header, you must add the interface of the fortran function to your documentation. Each line of this interface must begin with the > symbol and end with n (a backslash and the letter n).

For example, if the previous function is an API function, its documentation becomes the following:

/**
* \param mesh pointer to the mesh structure.
* \param filename pointer to the name of file.
* \return 0 if failed, 1 otherwise.
*
* Save mesh data.
*
* \warning you must call the \a _MMG3D_packMesh function before saving your
* mesh.
*
* \remark Fortran interface:
* >   SUBROUTINE MMG3D_saveMesh(mesh,filename,strlen,retval)\n
* >     MMG5_DATA_PTR_T, INTENT(INOUT) :: mesh\n
* >     CHARACTER(LEN=*), INTENT(IN)   :: filename\n
* >     INTEGER, INTENT(IN)            :: strlen\n
* >     INTEGER, INTENT(OUT)           :: retval\n
* >   END SUBROUTINE\n
*
*/
int MMG3D_saveMesh(MMG5_pMesh mesh, char *filename);

II/ Where

Comments only your functions in the .c file, except for the API functions; these must be documentated in the appropriate libmmg<X>.h file (and only there).

Memory management: dynamic allocations and deallocations

We need to control the memory consumption in our applications so the memory used by dynamic allocations is counted and updated at each allocation and deallocation.

Note that with a high verbosity (at least 6), you can check that at the end of the process the memory count is 0.

To make the update of memory consumption easier, we have wrapped the malloc, calloc, realloc and free functions into macros that must be called in place of these functions.

C function

mmg macro

ptr = (type *) malloc(size*sizeof(type));

MMG5_SAFE_MALLOC(ptr,size,type,law);

ptr = (type *) calloc(size,sizeof(type));

MMG5_SAFE_CALLOC(ptr,size,type,law);

ptr = (type *) realloc(ptr,size*sizeof(type)); if ( high_verbosity ) printf('  ## Warning:%s:%d: %s reallocation.\n',__FILE__,__LINE__,tab_info);

MMG5_SAFE_REALLOC(ptr,prevSize,newSize,type,tab_name,law);

Decrease_memory_count(size); free(ptr); ptr = NULL;

MMG5_DEL_MEM(mesh,ptr)

Note that other macros which aim to help to manage the memory have been implemented.

I/ Allocations

To check that we have enough memory to allocate a pointer of size siz and to increment the memory counter, you must precede your allocation by a call to the MMG5_ADD_MEM(mesh, siz, “tab_name”, law) macro.

For example, the following allocation:

Increase_memory_count(5*sizeof(double));
ptr = (double *) malloc (5*sizeof(double));
if ( !ptr ) {
  fprintf(stdout,"  ## Error: unable to allocate my array.");
  exit(EXIT_FAILURE);
}

must be replaced by the following one in the mmg code:

MMG5_ADD_MEM(mesh,5*sizeof(double),"my array",exit(EXIT_FAILURE));
MMG5_SAFE_MALLOC(ptr,5,double,exit(EXIT_FAILURE));

That said, calling exit from a library function is not polite. You may wish to do something else in the law argument, for example setting a flag that tells your function to free any memory it allocated and return a value indicating failure.

II/ Deallocations

To decrement the memory counter, to deallocate your pointer and to leave it pointing toward NULL, you just need to call the MMG5_DEL_MEM(mesh,ptr) macro.

To deallocate the memory allocated in the previous example, instead of the following code:

Decrease_memory_count(5*sizeof(double));
free(ptr);
ptr = NULL;

just write:

MMG5_DEL_MEM(mesh,ptr);