L'utilisation de MATLAB avec Yalmip et CPLEX pour optimiser la charge et décharge des véhicules électriques dans le but de minimiser l'écart maximal entre les pointes et les creux de charge. Le code fourni est fonctionnel et comprend des explications détaillées.
Dans le domaine des systèmes électriques, la gestion coordonnée de la charge et décharge des véhicules électriques revêt une importance capitale pour l'équilibre des charges réseau et l'amélioration de la stabilité du système électrique. Ce présent article expose comment exploiter MATLAB couplé à Yalmip et au solveur CPLEX pour résoudre le problème d'optimisation de la charge et décharge des véhicules électriques, avec comme objectif de minimiser l'écart entre les pointes et les creux de charge totale.
Aprpoche générale
L'objectif consiste à optimiser les stratégies de charge et décharge des véhicules électriques afin de réduire au minimum l'écart entre les pointes et les creux de charge du réseau. Cela implique le contrôle de la puissance de charge et décharge des véhicules électriques à chaque intervalle de temps, tout en respectant diverses contraintes telles que la capacité de la batterie, les limites de puissance de charge et décharge, etc.
Implémentation du code
2.1 Initialisation et définition des paramètres
% Nettoyage de l'environnement de travail
clear all; clc;
% Définition de l'intervalle temporel (en heures)
intervalle_temps = 1;
% Période totale de simulation (en heures)
periode_totale = 24;
% Nombre de véhicules électriques
nb_vehicules = 10;
% État initial de charge pour chaque véhicule (en kWh)
etat_initial = repmat(20, nb_vehicules, 1);
% Capacité maximale de la batterie pour chaque véhicule (en kWh)
capacite_max = repmat(50, nb_vehicules, 1);
% Puissance maximale de charge pour chaque véhicule (en kW)
puissance_charge_max = repmat(3, nb_vehicules, 1);
% Puissance maximale de décharge pour chaque véhicule (en kW)
puissance_decharge_max = repmat(3, nb_vehicules, 1);
% Charge de base du réseau (en kW), courbe de charge quotidienne typique
charge_base = [100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 240 230 220 210 200 190 180 170];
Dans cette section de code, nous définissons plusieurs paramètres clés. Il s'agit de l'intervalle temporel intervalle_temps, de la période totale periode_totale, du nombre de véhicules électriques nb_vehicules, de l'état initial de charge etat_initial, de la capacité maximale de la batterie capacite_max, ainsi que des puissances maximales de charge et décharge puissance_charge_max et puissance_decharge_max. Nous définissons également la charge de base charge_base, qui représente la charge du réseau sans prendre en compte les véhicules élcetriques.
2.2 Définition des variables d'optimisation
% Définition des variables d'optimisation
% Puissance de charge, puissance_charge(i,j) représente la puissance de charge du véhicule i à l'intervalle j
puissance_charge = sdpvar(nb_vehicules, periode_totale, 'full');
% Puissance de décharge, puissance_decharge(i,j) représente la puissance de décharge du véhicule i à l'intervalle j
puissance_decharge = sdpvar(nb_vehicules, periode_totale, 'full');
% Charge totale à chaque intervalle
charge_totale = sdpvar(1, periode_totale, 'full');
% Pointe de charge
pointe_charge = sdpvar(1, 1, 'full');
% Creux de charge
creux_charge = sdpvar(1, 1, 'full');
Ici, nous utilisons la fonction sdpvar de Yalmip pour définir nos variables d'optimisation. puissance_charge et puissance_decharge représentent respectivement la puissance de charge et de décharge de chaque véhicule électrique à chaque intervalle de temps. charge_totale est utilisée pour enregistrer la charge totale à chaque intervalle, tandis que pointe_charge et creux_charge serviront à déterminer respectivement la pointe et le creux de charge.
2.3 Conditions de contrainte
% Conditions de contrainte
contraintes = [];
% Puissance de charge non négative
for vehicule = 1:nb_vehicules
for intervalle = 1:periode_totale
contraintes = [contraintes, puissance_charge(vehicule, intervalle) >= 0];
end
end
% Puissance de décharge non négative
for vehicule = 1:nb_vehicules
for intervalle = 1:periode_totale
contraintes = [contraintes, puissance_decharge(vehicule, intervalle) >= 0];
end
end
% Limites de puissance de charge
for vehicule = 1:nb_vehicules
for intervalle = 1:periode_totale
contraintes = [contraintes, puissance_charge(vehicule, intervalle) <= puissance_charge_max(vehicule)];
end
end
% Limites de puissance de décharge
for vehicule = 1:nb_vehicules
for intervalle = 1:periode_totale
contraintes = [contraintes, puissance_decharge(vehicule, intervalle) <= puissance_decharge_max(vehicule)];
end
end
% Évolution dynamique de l'état de charge
for vehicule = 1:nb_vehicules
niveau_charge = etat_initial(vehicule);
for intervalle = 1:periode_totale
niveau_charge = niveau_charge + (puissance_charge(vehicule, intervalle) - puissance_decharge(vehicule, intervalle)) * intervalle_temps;
contraintes = [contraintes, niveau_charge >= 0, niveau_charge <= capacite_max(vehicule)];
end
end
% Calcul de la charge totale à chaque intervalle
for intervalle = 1:periode_totale
contraintes = [contraintes, charge_totale(intervalle) == charge_base(intervalle) + sum(puissance_charge(:, intervalle)) - sum(puissance_decharge(:, intervalle))];
end
% Contraintes pour la pointe de charge
for intervalle = 1:periode_totale
contraintes = [contraintes, charge_totale(intervalle) <= pointe_charge];
end
% Contraintes pour le creux de charge
for intervalle = 1:periode_totale
contraintes = [contraintes, charge_totale(intervalle) >= creux_charge];
end
Cette section de code établit diverses conditions de contrainte. Tout d'abord, nous nous assurons que les puissances de charge et de décharge sont non négatives et ne dépassent pas leurs limites maximales respectives. Ensuite, en nous basant sur l'équation d'évolution dynamique de l'état de charge, nous garantissons que le niveau de batterie reste dans des limites raisonnables à chaque intervalle. Nous calculons ensuite la charge totale à chaque intervalle en additionnant la charge de base, les puissances de charge et en soustrayant les puissances de décharge. Enfin, nous déterminons les contraintes pour la pointe et le creux de charge.
2.4 Foncsion objectif
% Fonction objectif : minimisation de l'écart entre pointe et creux de charge
objectif = minimize(pointe_charge - creux_charge);
Ici, nous définissons clairement notre fonction objectif, qui consiste à minimiser l'écart entre la pointe et le creux de charge. Cela orientera l'algorithme d'optimisation vers une stratégie de charge et décharge des véhicules électriques qui rendra la charge du réseau aussi stable que possible.
2.5 Résolution du problème
% Appel du solveur CPLEX
options = sdpsettings('verbose', 1, 'solver', 'cplex');
statut = optimize(contraintes, objectif, options);
Via la fonction optimize, et en spécifiant CPLEX comme solveur, nous transmettons les contraintes et la fonction objectif définies précédemment au solveur, lui permettant de trouver la solution optimale.
2.6 Affichage des résultats
% Extraction de la solution optimale
if statut == 'infeasible'
disp('Le problème est infaisable. Vérifiez les contraintes.');
return;
end
puissance_charge_opt = value(puissance_charge);
puissance_decharge_opt = value(puissance_decharge);
charge_totale_opt = value(charge_totale);
pointe_charge_opt = value(pointe_charge);
creux_charge_opt = value(creux_charge);
% Affichage des résultats
disp('Solution optimale - Puissances de charge :');
disp(puissance_charge_opt);
disp('Solution optimale - Puissances de décharge :');
disp(puissance_decharge_opt);
disp('Solution optimale - Charge totale :');
disp(charge_totale_opt);
disp('Pointe de charge :');
disp(pointe_charge_opt);
disp('Creux de charge :');
disp(creux_charge_opt);
% Tracé de la courbe de charge totale
figure;
plot(1:periode_totale, charge_totale_opt, 'b', 'LineWidth', 1.5);
xlabel('Intervalle de temps (heures)');
ylabel('Charge totale (kW)');
title('Courbe de charge totale après optimisation');
grid on;
Enfin, nous extrayons et affichons la solution optimale, y compris les puissances optimales de charge et de décharge pour chaque véhicule électrique à chaque intervalle, la charge totale optimale à chaque intervalle, ainsi que la pointe et le creux de charge. Nous traçons également la courbe de charge totale après optimisation, offrant une visualisation claire de l'efficacité de l'optimisation.
Grâce à ces étapes, nous avons réussi à utiliser MATLAB couplé à Yalmip et CPLEX pour résoudre le problème d'optimisation de la charge et décharge des véhicules électriques avec comme objectif de minimiser l'écart entre les pointes et les creux de charge totale. Nous espérons que ce partage sera utile aux personnes travaillant sur l'optimisation des systèmes électriques.