Skip to content

Commit cf4d7a1

Browse files
committed
preliminary work on adding more solvers
1 parent 44fc5c0 commit cf4d7a1

File tree

6 files changed

+279
-0
lines changed

6 files changed

+279
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import argparse
2+
import pickle
3+
from qiskit_nature.second_q.drivers import PySCFDriver
4+
5+
parser = argparse.ArgumentParser(
6+
prog="PySCF Driver for Material Simulation",
7+
description="A CLI Program to get a ElectronicStructureProblem for a Material Simulation"
8+
)
9+
parser.add_argument("input_file")
10+
parser.add_argument("output_file")
11+
parser.add_argument("--charge", type=int, default=0, help="Charge of the molecule")
12+
parser.add_argument("--spin", type=int, default=0, help="Spin of the molecule")
13+
args = parser.parse_args()
14+
15+
with open(args.input_file, 'r') as input_file:
16+
molecule = input_file.read().strip()
17+
18+
19+
driver = PySCFDriver(
20+
atom=molecule,
21+
basis="sto3g",
22+
charge=charge,
23+
spin=spin
24+
)
25+
26+
problem = driver.run()
27+
28+
with open(args.output_file, 'wb') as output_file:
29+
pickle.dump(problem, output_file)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
qiskit == 1.4.3
2+
qiskit-nature == 0.7.2
3+
pyscf == 2.9.0
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package edu.kit.provideq.toolbox.materialsimulation.ansatzes;
2+
3+
import edu.kit.provideq.toolbox.meta.ProblemSolver;
4+
import edu.kit.provideq.toolbox.meta.ProblemType;
5+
6+
/**
7+
* An abstract class representing an Ansatz for material simulation problems.
8+
*/
9+
public abstract class Ansatz implements ProblemSolver<String, String> {
10+
11+
@Override
12+
public ProblemType<String, String> getProblemType() {
13+
return AnsatzConfiguration.MATERIAL_SIMULATION_ANSATZ;
14+
}
15+
16+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package edu.kit.provideq.toolbox.materialsimulation.ansatzes;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
6+
import de.ovgu.featureide.fm.core.io.Problem;
7+
import edu.kit.provideq.toolbox.ResourceProvider;
8+
import edu.kit.provideq.toolbox.meta.ProblemManager;
9+
import edu.kit.provideq.toolbox.meta.ProblemType;
10+
11+
@Configuration
12+
public class AnsatzConfiguration {
13+
/**
14+
* A Configuration for Ansatzes used in Material Simulation.
15+
*/
16+
public static final ProblemType<String, String> MATERIAL_SIMULATION_ANSATZ = new ProblemType<>(
17+
"material-simulation-ansatz",
18+
String.class,
19+
String.class
20+
);
21+
22+
@Bean
23+
ProblemManager<String, String> getMaterialSimulationAnsatzesManager(
24+
ResourceProvider resourceProvider) {
25+
return new ProblemManager<>(
26+
MATERIAL_SIMULATION_ANSATZ,
27+
Set.of(new HartreeFockAnsatz(), new UCCSDAnsatz(), new UCCSDTAnsatz()),
28+
Set.of(new Problem<>(MATERIAL_SIMULATION_ANSATZ))
29+
);
30+
}
31+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package edu.kit.provideq.toolbox.materialsimulation.ansatzes;
2+
3+
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.beans.factory.annotation.Value;
5+
import org.springframework.context.ApplicationContext;
6+
import org.springframework.stereotype.Component;
7+
8+
import edu.kit.provideq.toolbox.Solution;
9+
import edu.kit.provideq.toolbox.meta.SolvingProperties;
10+
import edu.kit.provideq.toolbox.meta.SubRoutineResolver;
11+
import reactor.core.publisher.Mono;
12+
13+
@Component
14+
public class UCCSDAnsatz extends Ansatz {
15+
private final String scriptPath;
16+
private final String venv;
17+
private final ApplicationContext context;
18+
19+
@Autowired
20+
public UCCSDAnsatz(
21+
@Value("${path.custom.materialsimulation-ansatz-uccsd}") String scriptPath,
22+
@Value("${venv.custom.materialsimulation-ansatz-uccsd}") String venv,
23+
ApplicationContext context
24+
) {
25+
this.scriptPath = scriptPath;
26+
this.venv = venv;
27+
this.context = context;
28+
}
29+
30+
@Override
31+
public String getName() {
32+
return "UCCSD Ansatz";
33+
}
34+
35+
@Override
36+
public String getDescription() {
37+
return "The UCCSD Ansatz is an ansatz for quantum chemistry calculations "
38+
+ "that uses the unitary coupled cluster singles and doubles method.";
39+
}
40+
41+
@Override
42+
public Mono<Solution<String>> solve(
43+
String input,
44+
SubRoutineResolver resolver,
45+
SolvingProperties properties
46+
) {
47+
// Implementation of the UCCSD Ansatz solving logic goes here.
48+
// For now, we return an empty Mono as a placeholder.
49+
return Mono.empty();
50+
}
51+
52+
53+
}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
package edu.kit.provideq.toolbox.materialsimulation.solvers;
2+
3+
import java.util.List;
4+
import java.util.Optional;
5+
6+
import org.springframework.stereotype.Component;
7+
import org.springframework.beans.factory.annotation.Autowired;
8+
import org.springframework.beans.factory.annotation.Value;
9+
import org.springframework.context.ApplicationContext;
10+
11+
import edu.kit.provideq.toolbox.Solution;
12+
import edu.kit.provideq.toolbox.materialsimulation.ansatzes.AnsatzConfiguration;
13+
import edu.kit.provideq.toolbox.materialsimulation.MaterialSimulationConfiguration;
14+
import edu.kit.provideq.toolbox.meta.SolvingProperties;
15+
import edu.kit.provideq.toolbox.meta.SubRoutineDefinition;
16+
import edu.kit.provideq.toolbox.meta.SubRoutineResolver;
17+
import edu.kit.provideq.toolbox.meta.setting.SolverSetting;
18+
import edu.kit.provideq.toolbox.meta.setting.basic.IntegerSetting;
19+
import edu.kit.provideq.toolbox.process.ProcessRunner;
20+
import edu.kit.provideq.toolbox.process.PythonProcessRunner;
21+
import reactor.core.publisher.Mono;
22+
import reactor.core.scheduler.Schedulers;
23+
24+
25+
/**
26+
* {@link MaterialSimulationConfiguration#MATERIAL_SIMULATION} "solver" using a PySCF implementation.
27+
* It creates an electronic structure problem using a PySCF driver for material simulation.
28+
* It allows to define the charge and spin of the molecule.
29+
*/
30+
@Component
31+
public class PyscfDriver extends MaterialSimulationSolver {
32+
private static final SubRoutineDefinition<String, String> ANSATZ_SUBROUTINE =
33+
new SubRoutineDefinition<>(AnsatzConfiguration.MATERIAL_SIMULATION_ANSATZ, "Which Ansatz should be used?");
34+
private final String scriptPath;
35+
private final String venv;
36+
private final ApplicationContext context;
37+
38+
private static final String SETTING_CHARGE = "Charge";
39+
private static final int DEFAULT_CHARGE = 0;
40+
41+
private static final String SETTING_SPIN = "Spin";
42+
private static final int DEFAULT_SPIN = 0;
43+
44+
@Autowired
45+
public PyscfDriver(
46+
@Value("${path.custom.materialsimulation-driver-pyscf}") String scriptPath,
47+
@Value("${venv.custom.materialsimulation-driver-pyscf}") String venv,
48+
ApplicationContext context) {
49+
this.scriptPath = scriptPath;
50+
this.venv = venv;
51+
this.context = context;
52+
}
53+
54+
@Override
55+
public String getName() {
56+
return "PySCF Driver";
57+
}
58+
59+
@Override
60+
public String getDescription() {
61+
return "Creates an Electronic Structure Problem using the Pyscf Driver "
62+
+ "for Material Simulation. It allows to define the charge and spin of the molecule.";
63+
}
64+
65+
@Override
66+
public List<SolverSetting> getSolverSettings() {
67+
return List.of(
68+
new IntegerSetting(
69+
SETTING_CHARGE,
70+
"The charge of the molecule. The parameter to define "
71+
+ "the total number of electrons in the system.",
72+
DEFAULT_CHARGE,
73+
0, Integer.MAX_VALUE
74+
),
75+
new IntegerSetting(
76+
SETTING_SPIN,
77+
"The spin of the molecule. Equals the number of unpaired electrons 2S,"
78+
+ " i.e. the difference between the number of alpha and beta electrons.",
79+
DEFAULT_SPIN,
80+
0, Integer.MAX_VALUE
81+
)
82+
);
83+
}
84+
85+
@Override
86+
public Mono<Solution<String>> solve(
87+
String input,
88+
SubRoutineResolver subRoutineResolver,
89+
SolvingProperties properties
90+
) {
91+
var solution = new Solution<>(this);
92+
93+
int charge = properties.<IntegerSetting>getSetting(SETTING_CHARGE)
94+
.map(IntegerSetting::getValue)
95+
.orElse(DEFAULT_CHARGE);
96+
97+
int spin = properties.<IntegerSetting>getSetting(SETTING_SPIN)
98+
.map(IntegerSetting::getValue)
99+
.orElse(DEFAULT_SPIN);
100+
101+
if (charge < 0) {
102+
throw new IllegalArgumentException("Charge must be non-negative");
103+
}
104+
if (spin < 0) {
105+
throw new IllegalArgumentException("Spin must be non-negative");
106+
}
107+
108+
var processResult = context
109+
.getBean(PythonProcessRunner.class, scriptPath, venv)
110+
.withArguments(
111+
ProcessRunner.INPUT_FILE_PATH,
112+
ProcessRunner.OUTPUT_FILE_PATH,
113+
"--charge", String.valueOf(charge),
114+
"--spin", String.valueOf(spin)
115+
)
116+
.writeInputFile(input)
117+
.readOutputFile()
118+
.run(getProblemType(), solution.getId());
119+
120+
Optional<String> output = processResult.output();
121+
if (!processResult.success() || output.isEmpty()) {
122+
solution.setDebugData(processResult.errorOutput().orElse("Unknown error occurred."));
123+
solution.abort();
124+
return Mono.just(solution);
125+
}
126+
127+
128+
129+
return subRoutineResolver.runSubRoutine(ANSATZ_SUBROUTINE, output.get())
130+
.publishOn(Schedulers.boundedElastic()) // avoids blocking from Files.writeString() in try/catch
131+
.map(subRoutineSolution -> {
132+
if (subRoutineSolution.getSolutionData() == null
133+
|| subRoutineSolution.getSolutionData().isEmpty()) {
134+
solution.setDebugData("Subroutine did not return a valid solution.");
135+
solution.abort();
136+
return solution;
137+
}
138+
139+
solution.setSolutionData(subRoutineSolution.getSolutionData());
140+
solution.complete();
141+
142+
return solution;
143+
}
144+
);
145+
}
146+
}
147+

0 commit comments

Comments
 (0)