79 {
83 input.cmdOptionExists("-nThreads")
84 ? std::stoi(input.getCmdOption("-nThreads"))
85 : 4);
86 auto opt = [&input](const char *f, const std::string &fb) {
87 return input.cmdOptionExists(f) ? input.getCmdOption(f) : fb;
88 };
89
90 const std::string model = opt("-model", "PDState");
91 const size_t dim = std::stoul(opt("-dim", "2"));
92 const bool plane_strain = std::stoi(opt("-planeStrain", "0")) != 0;
93 const int influence = std::stoi(opt("-influence", "0"));
94 const double m_ratio = std::stod(opt("-m", "4"));
95 const double h = std::stod(opt("-h", dim == 2 ? "0.02" : "0.05"));
96 const double tol = std::stod(opt(
"-tol",
"0.02"));
97 const double L = std::stod(opt("-L", "1.0")), horizon = m_ratio * h;
98 const double E = 1.0e5, Gc = 10.;
99
100 double nu = std::stod(opt("-nu", "0.3"));
101 if (model != "PDState")
102 nu = (dim == 2 && !plane_strain) ? 1. / 3. : 0.25;
103
104 const double mu =
E / (2. * (1. + nu));
105 const double lambda = (dim == 2 && !plane_strain)
106 ? E * nu / (1. - nu * nu)
107 :
E * nu / ((1. + nu) * (1. - 2. * nu));
108
109 namespace fs = std::filesystem;
110 struct Check { std::string name; double got, want; };
111
112
113 auto runChecks = [&](const std::string &mname) {
114 const fs::path out = fs::current_path() /
115 std::format("calib_{}_{}d_{}_J{}", mname, dim,
116 plane_strain ? "pstrain" : "pstress", influence);
117 fs::create_directories(out);
118 auto deck = std::make_shared<inp::Input>(
119 makeDeck(mname, dim, plane_strain, influence, L, h, horizon, E, nu, Gc,
120 out.string() + "/"));
122 dem.init();
123
124
125
126 auto inside = [&](
const util::Point &x,
double margin) {
127 const double c = 0.5 * L - margin - 1.5 * h;
128 return std::abs(x.
d_x) < c && std::abs(x.
d_y) < c &&
129 (dim == 2 || std::abs(x.
d_z) < c);
130 };
131
132
133
134 auto evaluate =
136 for (size_t i = 0; i < dem.d_xRef.size(); i++) {
137 dem.d_u[i] = u(dem.d_xRef[i]);
138 dem.d_x[i] = dem.d_xRef[i] + dem.d_u[i];
139 }
140 dem.computeForces();
141 double e = 0., fx = 0., fy = 0.;
142 size_t ne = 0, nf = 0;
143 for (size_t i = 0; i < dem.d_xRef.size(); i++) {
144 if (inside(dem.d_xRef[i], horizon)) {
145 e += dem.d_e[i];
146 ne++;
147 }
148 if (inside(dem.d_xRef[i], 2. * horizon)) {
149 fx += dem.d_f[i].d_x;
150 fy += dem.d_f[i].d_y;
151 nf++;
152 }
153 }
154 return std::array<double, 3>{e / ne, fx / nf, fy / nf};
155 };
156
157 const double eps = 1.0e-5, a = 1.0e-5 / L;
158 std::vector<Check> checks;
159
160
163 checks.push_back({"energy uniaxial strain", r[0],
164 0.5 * (lambda + 2. * mu) * eps * eps});
167 checks.push_back({"energy equibiaxial", r[0],
168 (mu * dim + 0.5 * lambda * dim * dim) * eps * eps});
171 checks.push_back({"energy shear", r[0], 2. * mu * eps * eps});
172
173
176 checks.push_back({"force (lambda+2mu)", r[1], (lambda + 2. * mu) * a});
179 checks.push_back({"force mu", r[2], mu * a});
180
182 "CALIB model={} dim={} {} J={} delta/h={} nodes={} E={} nu={:.4f}\n",
183 mname, dim, plane_strain ? "plane_strain" : "plane_stress", influence,
184 m_ratio, dem.d_xRef.size(),
E, nu));
185 return checks;
186 };
187
188
189
190 std::vector<Check> checks;
191 try {
192 checks = runChecks(model);
193 if (input.cmdOptionExists("-compareModel")) {
194 const auto ref = runChecks(input.getCmdOption("-compareModel"));
195 for (size_t k = 0; k < checks.size(); k++)
196 checks[k].want = ref[k].got;
197 }
198 } catch (const std::exception &e) {
199
202 return 1;
203 }
204
205 bool ok = true;
206 for (const auto &c : checks) {
207 const double rel = (c.got - c.want) / c.want;
208 const bool pass = std::abs(rel) <=
tol;
209 ok = ok && pass;
210 util::io::print(std::format(
" {:<24} got={:+.15e} want={:+.6e} rel={:+.4f} {}\n",
211 c.name, c.got, c.want, rel, pass ? "OK" : "FAIL"));
212 }
215 return ok ? 0 : 1;
216}
json makeDeck(const std::string &model, size_t dim, bool plane_strain, int influence, double L, double h, double horizon, double E, double nu, double Gc, const std::string &out)
void print(const T &msg, int nt=print_default_tab, int printMpiRank=print_default_mpi_rank)
Prints formatted information.
void initNThreads(unsigned int nThreads=std::thread::hardware_concurrency())
Initializes MpiStatus struct.
void initMpi(int argc=0, char *argv[]=nullptr)
Initializes MPI and also creates MpiStatus struct.
void finalizeMpi()
Call MPI_Finalize if this process initialized MPI.
A structure to represent 3d vectors.
double d_y
the y coordinate
double d_z
the z coordinate
double d_x
the x coordinate