Writing a custom fix to change bonds only once at the start of simulation

So I want to understand how fix is called in lammps because i have written the bonds change only it the initialization. I don’t understand when running the code the print statement is printed two times. Once before setting up verlet run and once after the run after writing a restart file.

#include "fix_bond_data.h"
#include "atom.h"
#include "update.h"
#include "comm.h"
#include "error.h"
#include <stdio.h>
#include "fix.h"
#include <iostream>

using namespace LAMMPS_NS;

FixBondData::FixBondData(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) {
  // Constructor: initialize any parameters if needed
}

FixBondData::~FixBondData() {
  // Destructor: clean up resources if needed
}

void FixBondData::init() {
  // Initialization: This function is called once at the start
  process_bond_data(); // Call the bond data processing function once during initialization
}

void FixBondData::process_bond_data() {
  // Access the bond data from LAMMPS
  for (int i = 0; i < atom->nlocal; ++i) { // Loop through local atoms
    int nbonds = atom->num_bond[i]; // Get number of bonds for atom i

    for (int j = 0; j < nbonds; ++j) {
      int atom1 = i; // Current atom
      int atom2 = atom->map(atom->bond_atom[i][j]); // Get the bonded atom ID
      int bond_type = atom->bond_type[i][j]; // Get the bond type
      
      // Process bond data (atom1 is bonded to atom2 with bond_type)
      printf("Bond between atom %d and atom %d (type %d)\n", atom1, atom2, bond_type);
    }
  }
}

int FixBondData::setmask() {
  int mask = 0;
  // No need for POST_FORCE since we are only running once at the start
  return mask; // Return an empty mask
}
For reference my input file for lammps looks like this

dimension           2
units               lj
atom_style          bond

# Read initial configuration
read_data           init_config.txt

# Define bonds (springs)
bond_style          harmonic
bond_coeff          1 200.0 1.0

# Define the neighbor list
neighbor            0.3 bin
neigh_modify        delay 5

group vertices id 1 2 3 4 5 6 7 8 9 10 11 20 21 30 31 40 41 50 51 60 61 70 71 80 81 90 91 92 93 94 95 96 97 98 99 100 

# Fix the vertex atoms so they don't move
fix freeze_vertices vertices setforce 0.0 0.0 0.0

# Integrate motion of all atoms except the fixed vertices
group mobile subtract all vertices

fix 1 mobile nve
fix 2 mobile langevin 1.0 1.0 1.0 48279

fix my_bond_data all bond/data


# Output atom properties
dump 1 all custom 100 ../lammps/trajectory/atoms.lammpstrj id type x y z

# Specify simulation settings
thermo 100

# Run the simulation for the required duration
run 10000

# Write a restart file
write_data ../lammps/restart.txt


And the output I am getting looks something like this

`Bond between atom 94 and atom 95 (type 1)
Bond between atom 95 and atom 96 (type 1)
Bond between atom 96 and atom 97 (type 1)
Bond between atom 97 and atom 98 (type 1)
Bond between atom 98 and atom 99 (type 1)
Setting up Verlet run ...
.......
......
Timesteps part 
......
Histogram: 1 0 0 0 0 0 0 0 0 0
Neighs:              0 ave           0 max           0 min
Histogram: 1 0 0 0 0 0 0 0 0 0

Total # of neighbors = 0
Ave neighs/atom = 0
Ave special neighs/atom = 26.06
Neighbor list builds = 1997
Dangerous builds = 1996
System init for write_data ...
Bond between atom 0 and atom 10 (type 1)
Bond between atom 0 and atom 1 (type 1)
Bond between atom 1 and atom 2 (type 1)
.....
.....
`

Because your system is initialized twice. Once for the run and a second time for write_data.

If you want your custom code to be executed only once and outside of a run, why make it a fix style and not a command style?

Well that is true. Inititally I thought of running this fix after every 1000 timesteps or so so I thought writing a fix was a good idea. Also the guide to writing custom fix was easily available so I wrote a custom fix.

Now that I think about it would be much better to use command style to do this task since I want it only once either at the start of at the end of the simulations. But unfortunately I could not find a good give to write a custom command style. Anyways I somehow wrote it.

#include "bond_data_command.h"
#include "atom.h"

namespace LAMMPS_NS {

BondDataCommand::BondDataCommand(LAMMPS *lmp) : Command(lmp)
 {

}

void BondDataCommand::run() {
    process_bond_data();
}

void BondDataCommand::process_bond_data() {
    // Access the bond data from LAMMPS and change it 
.....
.....

}

} // namespace LAMMPS_NS

Also it compiled after adding it to make file but how to implement it so it works with the input file?
Do I have to make changes to input.cpp?

Your code is not correct.
You don’t need “run” method but a “command” method.
Please see: 3.10. Input script command style — LAMMPS documentation

The way to have new command styles registered as valid input commands is the same as for fixes or pair styles through a macro in the header. There are plenty of examples in the LAMMPS distribution to learn from. Also, you can easily infer the necessary API from looking at the base class.

This makes no sense. Regardless of how you compile LAMMPS, it should always detect and include your added code.