def assign_charge(mol, force_recalc=False):
    mol.require("Aromatic")
    for i, nbrs in mol.neighbors_iter():
        atom = mol.atom(i)
        nbrcnt = len(nbrs)
        if atom.symbol == "N":
            if not atom.pi:
                mol.atom(i).charge_phys = 1
            elif nbrcnt == 1 and atom.pi == 2:
                ni = list(nbrs.keys())[0]
                conj = False
                sp2n = None
                for nni, nnb in mol.neighbors(ni).items():
                    if mol.atom(nni).symbol == "N" and nnb.order == 2 \
                            and not mol.atom(nni).aromatic:
                        mol.atom(nni).charge_conj = 1
                        conj = True
                    elif mol.atom(nni).symbol == "N" and nni != i:
                        sp2n = nni
                if conj:
                    mol.atom(i).charge_phys = 1
                    if sp2n is not None:
                        mol.atom(sp2n).charge_conj = 1
        elif atom.symbol == "O" and nbrcnt == 1 and atom.pi == 2:
            ni = list(nbrs.keys())[0]
            conj = False
            if mol.atom(ni).symbol == "N":
                mol.atom(i).n_oxide = True
                mol.atom(ni).n_oxide = True
            for nni, nnb in mol.neighbors(ni).items():
                if mol.atom(nni).symbol in ("O", "S") \
                        and nnb.order == 2 and not mol.atom(ni).n_oxide:
                    mol.atom(nni).charge_conj = -1
                    conj = True
            if conj:
                mol.atom(i).charge_phys = -1
        elif atom.symbol == "S" and nbrcnt == 1:
            ni = list(nbrs.keys())[0]
            if mol.atom(ni).aromatic:
                mol.atom(i).charge_phys = -1
    mol.charge_assigned = True
    mol.descriptors.add("Phys_charge")