1 /* Siconos is a program dedicated to modeling, simulation and control
2  * of non smooth dynamical systems.
3  *
4  * Copyright 2021 INRIA.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17 */
18 
19 #include <assert.h>                             // for assert
20 #include <stdio.h>                              // for printf
21 #include <stdlib.h>                             // for exit
22 #include "FischerBurmeister.h"                  // for phi_Mixed_FB
23 #include "MLCP_Solvers.h"                       // for mlcp_compute_error
24 #include "MixedLinearComplementarityProblem.h"  // for MixedLinearComplement...
25 #include "Newton_methods.h"                     // for functions_LSA, init_l...
26 #include "NumericsFwd.h"                        // for MixedLinearComplement...
27 #include "NumericsMatrix.h"                     // for NumericsMatrix
28 #include "SiconosBlas.h"                              // for cblas_dgemv, cblas_dcopy
29 
30 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
31 
FB_compute_F_mlcp(void * data_opaque,double * z,double * w)32 static void FB_compute_F_mlcp(void* data_opaque, double* z, double* w)
33 {
34   // Computation of the new value w = F(z) = Mz + q
35   // q --> w
36   MixedLinearComplementarityProblem* problem = (MixedLinearComplementarityProblem *)data_opaque;
37   assert(problem->M);
38   assert(problem->M->matrix0);
39   unsigned int n = problem->n;
40   unsigned int m = problem->m;
41   /* Problem in the form (M,q) */
42   if(problem->isStorageType1)
43   {
44     cblas_dcopy(n, problem->q, 1, w, 1);
45     // Mz+q --> w
46     cblas_dgemv(CblasColMajor, CblasNoTrans, n, n, 1.0, problem->M->matrix0, n, z, 1, 1.0, w, 1);
47   }
48   else
49   {
50     /* Links to problem data */
51     double *a = problem->q;
52     double *b = &problem->q[n];
53     double *A = problem->A;
54     double *B = problem->B;
55     double *C = problem->C;
56     double *D = problem->D;
57 
58     /* Compute "equalities" part, we = Au + Cv + a - Must be equal to 0 */
59     cblas_dcopy(n, a, 1, w, 1);    //  we = w[0..n-1] <-- a
60     cblas_dgemv(CblasColMajor, CblasNoTrans, n, n, 1.0, A, n, z, 1, 1.0, w, 1); // we <-- A*u + we
61     cblas_dgemv(CblasColMajor, CblasNoTrans, n, m, 1.0, C, m, &z[n], 1, 1.0, w, 1); // we <-- C*v + we
62 
63     /* Computes part which corresponds to complementarity */
64     double* w_c = &w[n]; // No copy!!
65     cblas_dcopy(m, b, 1, w_c, 1); //  wi = w[n..m] <-- b
66     cblas_dgemv(CblasColMajor, CblasNoTrans, m, n, 1.0, D, n, z, 1, 1.0, w_c, 1); // we <-- D*u + we
67     cblas_dgemv(CblasColMajor, CblasNoTrans, m, m, 1.0, B, m, &z[n], 1, 1.0, w_c, 1); // we <-- B*v + we
68   }
69 }
70 
FB_compute_H_mlcp(void * data_opaque,double * z,double * w,double * workV1,double * workV2,NumericsMatrix * H)71 static void FB_compute_H_mlcp(void* data_opaque, double* z, double* w, double* workV1, double* workV2, NumericsMatrix* H)
72 {
73   printf("MLCP FB_compute_H_mlcp not implemented yet");
74   exit(1);
75 #if 0
76   MixedLinearComplementarityProblem* data = (MixedLinearComplementarityProblem *)data_opaque;
77   unsigned int n = data->size;
78   assert(data->M);
79   assert(data->M->matrix0);
80   double* M = data->M->matrix0;
81   double normi;
82 
83   // workV1 = "z" in Facchibei--Pang p. 808
84   // "z_i" = 1 if z_i = w_i = 0.0
85   // M^T.workV1 --> workV2
86   cblas_dgemv(CblasColMajor, CblasTrans, n, n, 1.0, M, n, workV1, 1, 0.0, workV2, 1);
87   for(unsigned int i = 0; i < n; ++i)
88   {
89     if(workV1[i] != 0.0)  // i in beta
90     {
91       normi = sqrt(workV1[i] * workV1[i] + workV2[i] * workV2[i]);
92       for(unsigned int j = 0; j < n; j++)
93       {
94         H[j * n + i] = (workV2[i] / normi - 1.0) * M[j * n + i];
95       }
96       H[i * n + i] += (workV1[i] / normi - 1.0);
97 
98     }
99     else // i not in beta
100     {
101       normi = sqrt(z[i] * z[i] + w[i] * w[i]);
102       for(unsigned int j = 0; j < n; j++)
103       {
104         H[j * n + i] = (w[i] / normi - 1.0) * M[j * n + i];
105       }
106       H[i * n + i] += (z[i] / normi - 1.0);
107     }
108 
109   }
110 #endif
111 }
112 
mlcp_mixed_FB(void * data_opaque,double * z,double * F,double * F_FB)113 void mlcp_mixed_FB(void* data_opaque, double* z, double* F, double* F_FB)
114 {
115   phi_Mixed_FB(((MixedLinearComplementarityProblem *)data_opaque)->n, ((MixedLinearComplementarityProblem *)data_opaque)->m, z, F, F_FB);
116 }
117 
FB_compute_error_mlcp(void * data_opaque,double * z,double * w,double * nabla_theta,double tol,double * err)118 void FB_compute_error_mlcp(void* data_opaque, double* z, double* w, double* nabla_theta, double tol, double* err)
119 {
120   mlcp_compute_error((MixedLinearComplementarityProblem *)data_opaque, z, w, tol, err);
121 }
122 
mlcp_newton_FB(MixedLinearComplementarityProblem * problem,double * z,double * w,int * info,SolverOptions * options)123 void mlcp_newton_FB(MixedLinearComplementarityProblem* problem, double *z, double *w, int *info, SolverOptions* options)
124 {
125   functions_LSA functions_FBLSA_mlcp;
126   init_lsa_functions(&functions_FBLSA_mlcp, &FB_compute_F_mlcp, (compute_F_merit_ptr)&mlcp_FB);
127   functions_FBLSA_mlcp.compute_H = &FB_compute_H_mlcp;
128   functions_FBLSA_mlcp.compute_error = &FB_compute_error_mlcp;
129 
130   set_lsa_params_data(options, problem->M);
131   newton_LSA(problem->n + problem->m, z, w, info, (void *)problem, options, &functions_FBLSA_mlcp);
132 }
133 
134 
135